summaryrefslogtreecommitdiff
path: root/prolog/problems/lists_advanced/sum_2/en.py
blob: 3abc348855134927f90bd00ef6931c18b40bfb2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
name = 'sum/2'
slug = 'find the sum of all elements in list'

description = '''\
<p><code>sum(L, Sum)</code>: <code>Sum</code> is the sum of all elements in list <code>L</code>.</p>
<pre>
?- sum([1,2,3], Sum).
  Sum = 6.
</pre>'''

plan = ['''\
<p>The sum of an empty list is really not all that large. And if it's not empty, then we add it up,
element by element, recursively.</p>
''', '''\
<p>If the sum of the elements in the tail (list without a head) equals <code>SumT</code>, then the sum
of the elements in the whole list equals <code>SumT + H</code>.</p>
''', '''\
<p>If I take away the head, and the recursion solves this smaller problem (tail), and if I add the value
of the head to the result returned by the recursion, then I get the sum of the whole list.</p>
''']

hint = {
    'eq_instead_of_equ': '''\
<p>The operator <code>==</code> is "stricter" than operator <code>=</code> in the sense that
for the latter it is enough to be able to make the two operands equal (unification). Perhaps by using <code>=</code>
you can make the predicate <code>sum/2</code> more general (e.g. able to work with output arguments becoming inputs).</p>
<p>Of course, you can also solve the exercise without explicit use of either of these two operators, just
remember that unification is implicitly performed with the predicate's arguments (head of clause).</p>
''',

    'eq_instead_of_equ_markup': '''\
<p>Perhaps the operator for unification (=) would be better?</p>
''',

    'base_case': '''\
<p>Did you think of a base case? What's the sum of the elements in an empty list?</p>
''',

    'recursive_case': '''\
<p>The base case is ok. However, what about the general recursive case?</p>
''',

    'predicate_always_false': '''\
<p>It seems your predicate is <emph>always</emph> "false". Did you give it the correct name,
or is it perhaps misspelled?</p>
<p>If the name is correct, check whether something else is misspelled, perhaps there is a full stop instead of
a comma or vice versa, or maybe you typed a variable name in lowercase?</p>
<p>It is, of course, also possible that your conditions are too restrictive, or even impossible to satisfy
(as would be, for example, the condition that <code>N</code> is equal to <code>N + 1</code>,
or something similarly impossible).</p>
''',

    'timeout': '''\
<p>Is there an infinite recursion at work here? How will it ever stop?</p>
<p>Or perhaps is there a missing, faulty, or simply incompatible (with the general recursive case) base case?</p>
''',

    'arbitrary_base_case': '''\
<p>What's the sum of the elements in an empty list? Give a number!</p>
''',

    'args_not_instantiated': '''\
<p>The error that prolog reported means that when it encountered an arithmetic operation, not all the
values were known. Unfortunately, the ordering of goals is important when dealing with arithmetics.</p>
<p>Perhaps you can try moving the arithmetic operation more towards the end of the predicate?</p>
''',

    '=_instead_of_is': '''\
<p>Did you use the operator <code>=</code> instead of <code>is</code>? Operator <code>=</code> is used for
unification and tries to leave both its operands with as little modifications as possible while still making
them equal. Operator <code>is</code>, on the other hand, performs actual arithmetic evaluation of its
second operand and only then attempts the unification of both operands.</p>
''',

    '+1_instead_of_+H': '''\
<p>Did you really add one instead of the element's value? Copy/paste operation from the previous exercise? ;)</p>
''',

    'forcing_result_onto_recursion': '''
<p>Don't force the result onto recursion, don't tell it what it should return. Just assume it will do its job.
If this assumption is correct, then the rule will work for a larger case.</p>
<p>Is your recursive call of the form <code>sum(Tail, SumTail + H)</code>? This forces the recursive call to
return the sum of <em>the whole</em> list, not just the tail! This will not work. It is your job to
increase (by value of the head) the result returned by the recursion. In short, perform the addition
outside the recursive call.</p>
''',

    'same_var_on_both_sides_of_is': '''\
<p>Does one of your goals look similar to <code>N is N + 1</code>? Let's assume <code>N</code> is equal to 3.
With this goal you just stated that 3 must be equal to 4 (3+1). Prolog is a logical language and will
gladly say "false" to such a statement! Just use a new variable. The garbage collector will take care of
those not needed anymore automatically.</p>
''',
}