summaryrefslogtreecommitdiff
path: root/prolog/problems/lists_advanced
diff options
context:
space:
mode:
Diffstat (limited to 'prolog/problems/lists_advanced')
-rw-r--r--prolog/problems/lists_advanced/evenlen_1_+_oddlen_1/en.py71
-rw-r--r--prolog/problems/lists_advanced/evenlen_1_+_oddlen_1/sl.py7
-rw-r--r--prolog/problems/lists_advanced/len_2/en.py85
-rw-r--r--prolog/problems/lists_advanced/len_2/sl.py6
-rw-r--r--prolog/problems/lists_advanced/max_2/en.py87
-rw-r--r--prolog/problems/lists_advanced/max_2/sl.py5
-rw-r--r--prolog/problems/lists_advanced/min_2/en.py89
-rw-r--r--prolog/problems/lists_advanced/min_2/sl.py7
-rw-r--r--prolog/problems/lists_advanced/palindrome_1/en.py77
-rw-r--r--prolog/problems/lists_advanced/palindrome_1/sl.py11
-rw-r--r--prolog/problems/lists_advanced/rev_2/en.py6
-rw-r--r--prolog/problems/lists_advanced/shiftleft_2/en.py58
-rw-r--r--prolog/problems/lists_advanced/shiftleft_2/sl.py2
-rw-r--r--prolog/problems/lists_advanced/shiftright_2/en.py66
-rw-r--r--prolog/problems/lists_advanced/shiftright_2/sl.py2
-rw-r--r--prolog/problems/lists_advanced/sublist_2/en.py53
-rw-r--r--prolog/problems/lists_advanced/sublist_2/sl.py4
-rw-r--r--prolog/problems/lists_advanced/sum_2/en.py87
-rw-r--r--prolog/problems/lists_advanced/sum_2/sl.py6
19 files changed, 687 insertions, 42 deletions
diff --git a/prolog/problems/lists_advanced/evenlen_1_+_oddlen_1/en.py b/prolog/problems/lists_advanced/evenlen_1_+_oddlen_1/en.py
index 7e7a7d3..601488a 100644
--- a/prolog/problems/lists_advanced/evenlen_1_+_oddlen_1/en.py
+++ b/prolog/problems/lists_advanced/evenlen_1_+_oddlen_1/en.py
@@ -1,9 +1,10 @@
name = 'evenlen/1 + oddlen/1'
-slug = 'check if the length of a list is even or odd'
+slug = 'check if the length of a list is even or odd (without arithmetics)'
description = '''\
<p><code>evenlen(L)</code>: the list <code>L</code> has an even number of elements.<br />
<code>oddlen(L)</code>: the list <code>L</code> has an odd number of elements.</p>
+<p>Don't use arithmetic operations with this exercise, it destroys the point of it!</p>
<pre>
?- oddlen([1,2,3,4,5]).
true.
@@ -13,4 +14,70 @@ description = '''\
true.
</pre>'''
-hint = {}
+plan = ['''\
+<p>You can solve this exercise as two separate, albeit similar, ones, or as a single exercise that
+intertwines two predicates. The second option is probably more interesting.</p>
+''', '''\
+<p>Intertwining in this case means that one predicate calls the other and vice versa. Even. Odd. Even. Odd.</p>
+''', '''\
+<p>If the tail (list without a single head) is of <em>even</em> length, then the whole list is of
+<em>odd</em> length. And vice versa.</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 predicates <code>oddlen/1</code> and <code>evenlen/1</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 simplest case that you can trivially solve?</p>
+''',
+
+ 'extra_base_case': '''\
+<p>You're getting duplicate solutions. It's enough to only have a single base case for this pair of
+predicates; you don't need one for <code>evenlen/1</code> and one for <code>oddlen/1</code>.</p>
+''',
+
+ 'arbitrary_base_case': '''\
+<p>It seems that you accept an arbitrary result (a variable without an assigned value). This will not be ok.</p>
+<p>Note that <code>_</code> is not the same as <code>[_]</code>. The first pattern represents an arbitrary
+variable (anything), the second a list with <em>a single</em> arbitrary element.</p>
+''',
+
+ 'arithmetics_used': '''\
+<p>Please don't use arithmetics to solve this exercise, not even for counting the length of the list.
+It can be solved without that and it's also a much nicer idea or two.</p>
+''',
+
+'odd_and_even_mixed_up': '''\
+<p>Did you mix up odd and even? Zero is even, one is odd, two is... ;)</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>
+''',
+}
diff --git a/prolog/problems/lists_advanced/evenlen_1_+_oddlen_1/sl.py b/prolog/problems/lists_advanced/evenlen_1_+_oddlen_1/sl.py
index 000ce1a..1c0b596 100644
--- a/prolog/problems/lists_advanced/evenlen_1_+_oddlen_1/sl.py
+++ b/prolog/problems/lists_advanced/evenlen_1_+_oddlen_1/sl.py
@@ -4,6 +4,7 @@ slug = 'Brez aritmetike preveri, če je seznam sode ali lihe dolžine'
description = '''\
<p><code>evenlen(L)</code>: seznam <code>L</code> ima sodo število elementov.<br />
<code>oddlen(L)</code>: seznam <code>L</code> ima liho število elementov.</p>
+<p>Ne uporabljaj aritmetike pri tej nalogi, ker to uniči njeno poanto!</p>
<pre>
?- oddlen([1,2,3,4,5]).
true.
@@ -19,15 +20,15 @@ Druga verzija je verjetno bolj zanimiva.</p>
''', '''\
<p>Prepletanje tu pomeni, da ena naloga kliče drugo in obratno. Sodo. Liho. Sodo. Liho.</p>
''', '''\
-<p>Če je rep (seznam brez ene glave) <em>sode</em> dolžine, potem je celoten seznam </em>lihe</em> dolžine.
+<p>Če je rep (seznam brez ene glave) <em>sode</em> dolžine, potem je celoten seznam <em>lihe</em> dolžine.
In obratno.</p>
''']
hint = {
'eq_instead_of_equ': '''\
<p>Operator <code>==</code> je strožji od operatorja <code>=</code> v smislu, da je za slednjega dovolj,
-da elementa lahko naredi enaka (unifikacija). Morda z uporabo <code>=</code> narediš predikat
-<code>memb/2</code> delujoč tudi v kakšni drugi smeri.</p>
+da elementa lahko naredi enaka (unifikacija). Morda z uporabo <code>=</code> narediš predikata
+<code>oddlen/1</code> in <code>evenlen/1</code> delujoča tudi v kakšni drugi smeri.</p>
<p>Seveda pa lahko nalogo rešiš brez obeh omenjenih operatorjev, spomni se, da lahko unifikacijo narediš
implicitno že kar v argumentih predikata (glavi stavka).</p>
''',
diff --git a/prolog/problems/lists_advanced/len_2/en.py b/prolog/problems/lists_advanced/len_2/en.py
index 9202c2d..98eac2a 100644
--- a/prolog/problems/lists_advanced/len_2/en.py
+++ b/prolog/problems/lists_advanced/len_2/en.py
@@ -2,10 +2,91 @@ name = 'len/2'
slug = 'find the length of a list'
description = '''\
-<p><code>len(L, Len)</code>: <code>Len</code> is the length of the list <code>L</code>.</p>
+<p><code>len(L, Len)</code>: <code>Len</code> is the length of list <code>L</code>.</p>
<pre>
?- len([1,2,3], Len).
Len = 3.
</pre>'''
-hint = {}
+plan = ['''\
+<p>A list is not very long if it's empty, and if it's not empty it must have a head and a tail.</p>
+''', '''\
+<p>If the tail (list without a head) is of length <code>LenT</code>, then the whole list
+is of length <code>LenT + 1</code>.</p>
+''', '''\
+<p>If I take away the head, and the recursion solves this smaller problem (tail), and if I add 1 to the
+result returned by the recursion, then I get the length 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>len/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? Which list is the shortest list in the world?</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 <em>always</em> "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 length of 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>
+''',
+
+ '+H_instead_of_+1': '''\
+<p>Did you really add the element's value instead of its length (one)? ;)</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>len(Tail, LenTail + 1)</code>? This forces the recursive call to
+return the length of <em>the whole</em> list, not just the tail! This will not work. It is your job to
+increase by one the result returned by the recursion. In short, add one 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>
+''',
+}
diff --git a/prolog/problems/lists_advanced/len_2/sl.py b/prolog/problems/lists_advanced/len_2/sl.py
index c95796b..28fe25e 100644
--- a/prolog/problems/lists_advanced/len_2/sl.py
+++ b/prolog/problems/lists_advanced/len_2/sl.py
@@ -21,7 +21,7 @@ hint = {
'eq_instead_of_equ': '''\
<p>Operator <code>==</code> je strožji od operatorja <code>=</code> v smislu, da je za slednjega dovolj,
da elementa lahko naredi enaka (unifikacija). Morda z uporabo <code>=</code> narediš predikat
-<code>memb/2</code> delujoč tudi v kakšni drugi smeri.</p>
+<code>len/2</code> delujoč tudi v kakšni drugi smeri.</p>
<p>Seveda pa lahko nalogo rešiš brez obeh omenjenih operatorjev, spomni se, da lahko unifikacijo narediš
implicitno že kar v argumentih predikata (glavi stavka).</p>
''',
@@ -75,8 +75,8 @@ svoji levi strani.</p>
'forcing_result_onto_recursion': '''
<p>Ne vsiljuj rekurziji kaj naj vrne, prepusti se ji. To je tisti del, ko narediš predpostavko,
če je ta izpolnjena, potem bo tvoje pravilo delovalo za večji primer.</p>
-<p>Je tvoj rekurzivni klic oblike <code>len(T, LenT + 1)</code>? S tem vsiljuješ rekurziji
-da mora <emph>vrniti</emph> dolžino celega seznama in ne samo repa. To ni v redu, za ena moraš ti povečati
+<p>Je tvoj rekurzivni klic oblike <code>len(Tail, LenTail + 1)</code>? S tem vsiljuješ rekurziji
+da mora vrniti dolžino <em>celega</em> seznama in ne samo repa. To ni v redu, za ena moraš ti povečati
rezultat, ki ti ga rekurzija vrne. Skratka, prištevanje naredi izven rekurzivnega klica.</p>
''',
diff --git a/prolog/problems/lists_advanced/max_2/en.py b/prolog/problems/lists_advanced/max_2/en.py
index 59c00f0..fbdc612 100644
--- a/prolog/problems/lists_advanced/max_2/en.py
+++ b/prolog/problems/lists_advanced/max_2/en.py
@@ -2,7 +2,7 @@ name = 'max/2'
slug = 'find the largest element in list'
description = '''\
-<p><code>max(L, Max)</code>: <code>Max</code> is the largest value in the list <code>L</code>.</p>
+<p><code>max(L, Max)</code>: <code>Max</code> is the largest value in list <code>L</code>.</p>
<pre>
?- max([5,4,1,6], M).
M = 6.
@@ -10,4 +10,87 @@ description = '''\
M = 3.
</pre>'''
-hint = {}
+plan = ['''\
+<p>As usual, try to reduce the problem to a smaller one. Say you already have <em>the largest</em> element
+of the <em>tail</em>...</p>
+''', '''\
+<p>Compare the largest element in the tail (list without head <code>H</code>) with the value of head <code>H</code>,
+the larger of the two wins and gets returned.</p>
+''', '''\
+<p>If the given list <code>L</code> is composed of head <code>H</code> and tail <code>T</code>, and if we
+assume that some <code>MaxT</code> is the largest element in <code>T</code>, and if it's also true that
+the value of <code>H</code> is greater than <code>MaxT</code>, then <code>H</code> is the largest element
+in <code>L</code>. <em>Or</em> it is true that <code>H</code> is smaller than <code>MaxT</code>, and in this
+case <code>MaxT</code> is the largest element in <code>L</code>.</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>max/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 shortest list with an obvious largest element?</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>
+''',
+
+ 'empty_list_base_case': '''\
+<p>You'll be hard pressed to find the largest element of an empty list. What if you stop
+the recursion a bit earlier this time?</p>
+''',
+
+ 'list_instead_of_elem_base_case': '''\
+<p>You should return an element, not a list!</p>
+''',
+
+ 'duplicates_not_covered': '''\
+<p>The list can contain duplicate elements. Did you think of that?</p>
+''',
+
+ 'args_not_instantiated': '''\
+<p>The error that prolog reported means that when it encountered an arithmetic operation, not all the
+values were known.</p>
+<p>Did you perhaps forget that conjunction has higher precedence that disjunction and that every prolog's
+sentence (branch, rule) is independent in terms of the scope of the variables? This could be the problem.
+Carefully inspect both blocks of code (before and after the semicolon) or both rules.</p>
+''',
+
+ 'unprotected_branch': '''\
+<p>It seems you didn't "protect" one of the (conditional) branches. Both branches (of the disjunction) typically
+require a condition. Don't rely that if the execution reached the second branch that the first branch is false.
+The relation between them is OR and not XOR. It's your job to make them mutually exclusive. Try the following
+query and check <em>all possible</em> solutions and you'll notice the problem.</p>
+<p><code>?- max([6,9,3,8,1], Max).</code></p>
+''',
+
+ 'one_branch_missing': '''\
+<p>Maybe you forgot one of the possibilities? The head can be <em>either</em> greater <em>or</em> smaller than
+the largest element in the tail.</p>
+''',
+}
diff --git a/prolog/problems/lists_advanced/max_2/sl.py b/prolog/problems/lists_advanced/max_2/sl.py
index 0553e58..abd6cc5 100644
--- a/prolog/problems/lists_advanced/max_2/sl.py
+++ b/prolog/problems/lists_advanced/max_2/sl.py
@@ -11,7 +11,8 @@ description = '''\
</pre>'''
plan = ['''\
-<p>Kot vedno, poskusi prevesti na manjši problem. Recimo, da že imaš <em>največji</em> element v repu seznama...</p>
+<p>Kot vedno, poskusi prevesti na manjši problem. Recimo, da že imaš <em>največji</em> element v
+<em>repu</em> seznama...</p>
''', '''\
<p>Največji element v repu (seznamu brez glave <code>H</code>) primerjaj z vrednostjo glave <code>H</code>, tisti,
ki je večji zmaga in ga vrneš!</p>
@@ -27,7 +28,7 @@ hint = {
'eq_instead_of_equ': '''\
<p>Operator <code>==</code> je strožji od operatorja <code>=</code> v smislu, da je za slednjega dovolj,
da elementa lahko naredi enaka (unifikacija). Morda z uporabo <code>=</code> narediš predikat
-<code>memb/2</code> delujoč tudi v kakšni drugi smeri.</p>
+<code>max/2</code> delujoč tudi v kakšni drugi smeri.</p>
<p>Seveda pa lahko nalogo rešiš brez obeh omenjenih operatorjev, spomni se, da lahko unifikacijo narediš
implicitno že kar v argumentih predikata (glavi stavka).</p>
''',
diff --git a/prolog/problems/lists_advanced/min_2/en.py b/prolog/problems/lists_advanced/min_2/en.py
index a286cac..4835d9d 100644
--- a/prolog/problems/lists_advanced/min_2/en.py
+++ b/prolog/problems/lists_advanced/min_2/en.py
@@ -1,8 +1,8 @@
name = 'min/2'
-slug = 'find the smallest element'
+slug = 'find the smallest element of a list'
description = '''\
-<p><code>min(L, Min)</code>: <code>Min</code> is the smallest value in the list <code>L</code>.</p>
+<p><code>min(L, Min)</code>: <code>Min</code> is the smallest value in list <code>L</code>.</p>
<pre>
?- min([5,4,1,6], M).
M = 1.
@@ -10,4 +10,87 @@ description = '''\
M = 2.
</pre>'''
-hint = {}
+plan = ['''\
+<p>As usual, try to reduce the problem to a smaller one. Say you already have <em>the smallest</em> element
+of the <em>tail</em>...</p>
+''', '''\
+<p>Compare the smallest element in the tail (list without head <code>H</code>) with the value of head <code>H</code>,
+the smaller of the two wins and gets returned.</p>
+''', '''\
+<p>If the given list <code>L</code> is composed of head <code>H</code> and tail <code>T</code>, and if we
+assume that some <code>MinT</code> is the smallest element in <code>T</code>, and if it's also true that
+the value of <code>H</code> is smaller than <code>MinT</code>, then <code>H</code> is the smallest element
+in <code>L</code>. <em>Or</em> it is true that <code>H</code> is greater than <code>MinT</code>, and in this
+case <code>MinT</code> is the smallest element in <code>L</code>.</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>min/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 shortest list with an obvious smallest element?</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 <em>always</em> "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>
+''',
+
+ 'empty_list_base_case': '''\
+<p>You'll be hard pressed to find the smallest element of an empty list. What if you stop
+the recursion a bit earlier this time?</p>
+''',
+
+ 'list_instead_of_elem_base_case': '''\
+<p>You should return an element, not a list!</p>
+''',
+
+ 'duplicates_not_covered': '''\
+<p>The list can contain duplicate elements. Did you think of that?</p>
+''',
+
+ 'args_not_instantiated': '''\
+<p>The error that prolog reported means that when it encountered an arithmetic operation, not all the
+values were known.</p>
+<p>Did you perhaps forget that conjunction has higher precedence that disjunction and that every prolog's
+sentence (branch, rule) is independent in terms of the scope of the variables? This could be the problem.
+Carefully inspect both blocks of code (before and after the semicolon) or both rules.</p>
+''',
+
+ 'unprotected_branch': '''\
+<p>It seems you didn't "protect" one of the (conditional) branches. Both branches (of the disjunction) typically
+require a condition. Don't rely that if the execution reached the second branch that the first branch is false.
+The relation between them is OR and not XOR. It's your job to make them mutually exclusive. Try the following
+query and check <em>all possible</em> solutions and you'll notice the problem.</p>
+<p><code>?- min([1,9,3,8,6], Min).</code></p>
+''',
+
+ 'one_branch_missing': '''\
+<p>Maybe you forgot one of the possibilities? The head can be <em>either</em> greater <em>or</em> smaller than
+the smallest element in the tail.</p>
+''',
+}
diff --git a/prolog/problems/lists_advanced/min_2/sl.py b/prolog/problems/lists_advanced/min_2/sl.py
index bac4dc6..4a6975e 100644
--- a/prolog/problems/lists_advanced/min_2/sl.py
+++ b/prolog/problems/lists_advanced/min_2/sl.py
@@ -1,5 +1,5 @@
name = 'min/2'
-slug = 'Poišči najmanjši element v danem seznamu'
+slug = 'Poišči najmanjši element v seznamu'
description = '''\
<p><code>min(L, Min)</code>: <code>Min</code> je najmanjši element v seznamu <code>L</code>.</p>
@@ -11,7 +11,8 @@ description = '''\
</pre>'''
plan = ['''\
-<p>Kot vedno, poskusi prevesti na manjši problem. Recimo, da že imaš <em>najmanjši</em> element v repu seznama...</p>
+<p>Kot vedno, poskusi prevesti na manjši problem. Recimo, da že imaš <em>najmanjši</em> element v
+<em>repu</em> seznama...</p>
''', '''\
<p>Najmanjši element v repu (seznamu brez glave <code>H</code>) primerjaj z vrednostjo glave <code>H</code>, tisti,
ki je manjši zmaga in ga vrneš!</p>
@@ -27,7 +28,7 @@ hint = {
'eq_instead_of_equ': '''\
<p>Operator <code>==</code> je strožji od operatorja <code>=</code> v smislu, da je za slednjega dovolj,
da elementa lahko naredi enaka (unifikacija). Morda z uporabo <code>=</code> narediš predikat
-<code>memb/2</code> delujoč tudi v kakšni drugi smeri.</p>
+<code>min/2</code> delujoč tudi v kakšni drugi smeri.</p>
<p>Seveda pa lahko nalogo rešiš brez obeh omenjenih operatorjev, spomni se, da lahko unifikacijo narediš
implicitno že kar v argumentih predikata (glavi stavka).</p>
''',
diff --git a/prolog/problems/lists_advanced/palindrome_1/en.py b/prolog/problems/lists_advanced/palindrome_1/en.py
index bc6342b..8471ae2 100644
--- a/prolog/problems/lists_advanced/palindrome_1/en.py
+++ b/prolog/problems/lists_advanced/palindrome_1/en.py
@@ -8,6 +8,81 @@ description = '''\
true.
?- palindrome([1,2,3]).
false.
+?- palindrome([a,b,b,a]).
+ true.
</pre>'''
-hint = {}
+plan = ['''\
+<p>A palindrome is a list (ok, a word) that reads the same from front or back. Like aibohphobia!
+Was it a car or a cat I saw? ;)</p>
+''', '''\
+<p>As always we want to reduce the problem into a smaller one. Let's chop off the first and the last element
+of a list, and, if equal, proceed recursively.</p>
+''', '''\
+<p>If head <code>H</code> of list <code>L</code> is equal to the list's last element, and if the remainder
+(middle part) is a palindrome, then list <code>L</code> is also a palindrome.</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).</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? Which list represents the shortest possible palindrome?</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>
+''',
+
+ '[X,X]_instead_of_[]_base_case': '''\
+<p>Well, <code>[X,X]</code> is definitely a good base case. However, it doesn't cover one special case,
+and that is an empty list. Of course, this is a matter of definition (taste even?), but please correct it
+so that we all have solutions working in the same way.</p>
+''',
+
+ 'one_base_case_missing': '''\
+<p>Do you take <em>two</em> elements out with each recursive call? How does this end? Odd, even? ;)</p>
+<p>Try the following two queries. One will work nicely, the other one won't. What's the difference?</p>
+<p><code>?- palindrome([a,b,b,a]).</code></p>
+<p><code>?- palindrome([l,e,v,e,l]).</code></p>
+''',
+
+ 'arbitrary_base_case': '''\
+<p>Note that <code>_</code> is not the same as <code>[_]</code>. The first pattern represents an arbitrary
+variable (anything), the second a list with <em>a single</em> arbitrary element.</p>
+''',
+
+ 'last_used': '''\
+<p>By using predicate <code>last/2</code> it will be difficult to solve this exercise as it leaves the last
+element in the original list.</p>''',
+
+ 'final_hint_1': '''\
+<p>Interesting tidbit: do you know that you could have solved this exercise with just a single predicate call?
+What happens with the palindrome if you... hmm, reverse it? ;)</p>
+''',
+
+ 'final_hint_2': '''\
+<p>You can make the solution even shorter! How can you get rid of the operator <code>=</code> (<code>==</code>)
+or rather make it implicit?</p>
+''',
+}
diff --git a/prolog/problems/lists_advanced/palindrome_1/sl.py b/prolog/problems/lists_advanced/palindrome_1/sl.py
index 30a6bab..1e4e568 100644
--- a/prolog/problems/lists_advanced/palindrome_1/sl.py
+++ b/prolog/problems/lists_advanced/palindrome_1/sl.py
@@ -8,6 +8,8 @@ description = '''\
true.
?- palindrome([1,2,3]).
false.
+?- palindrome([a,b,b,a]).
+ true.
</pre>'''
plan = ['''\
@@ -22,8 +24,7 @@ palindrom, potem je tudi celoten seznam <code>L</code> palindrom.</p>
hint = {
'eq_instead_of_equ': '''\
<p>Operator <code>==</code> je strožji od operatorja <code>=</code> v smislu, da je za slednjega dovolj,
-da elementa lahko naredi enaka (unifikacija). Morda z uporabo <code>=</code> narediš predikat
-<code>memb/2</code> delujoč tudi v kakšni drugi smeri.</p>
+da elementa lahko naredi enaka (unifikacija).</p>
<p>Seveda pa lahko nalogo rešiš brez obeh omenjenih operatorjev, spomni se, da lahko unifikacijo narediš
implicitno že kar v argumentih predikata (glavi stavka).</p>
''',
@@ -50,8 +51,8 @@ da je <code>N</code> enako kot <code>N + 1</code> ali kaj podobno logično zlobn
''',
'[X,X]_instead_of_[]_base_case': '''\
-<p>Vsekakor je [X,X] povsem dober robni pogoj, a ne pokrije posebnega primera, ko je vhod kar prazen seznam. To je
-seveda stvar definicije, a da bomo imeli vsi enake rešitve, prosim, popravi.</p>
+<p>Vsekakor je <code>[X,X]</code> povsem dober robni pogoj, a ne pokrije posebnega primera, ko je vhod kar
+prazen seznam. To je seveda stvar definicije, a da bomo imeli vsi enake rešitve, prosim, popravi.</p>
''',
'one_base_case_missing': '''\
@@ -62,7 +63,7 @@ seveda stvar definicije, a da bomo imeli vsi enake rešitve, prosim, popravi.</p
''',
'arbitrary_base_case': '''\
-<p>Pazi <code>_</code> ni enako kot <code>[_]</code>. Prvo predstavlja poljubno spremenljivko, drugo seznam
+<p>Pazi, <code>_</code> ni enako kot <code>[_]</code>. Prvo predstavlja poljubno spremenljivko, drugo seznam
z <em>enim</em> poljubnim elementom.</p>
''',
diff --git a/prolog/problems/lists_advanced/rev_2/en.py b/prolog/problems/lists_advanced/rev_2/en.py
index 3b85a74..790d664 100644
--- a/prolog/problems/lists_advanced/rev_2/en.py
+++ b/prolog/problems/lists_advanced/rev_2/en.py
@@ -25,7 +25,7 @@ and if I assume the recursion reverses tail <code>T</code> into reversed tail <c
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 two elements equal (unification). Perhaps by using <code>=</code>
+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>rev/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>
@@ -44,7 +44,7 @@ remember that unification is implicitly performed with the predicate's arguments
''',
'predicate_always_false': '''\
-<p>It seems your predicate is <emph>always</emph> "false". Did you give it the correct name,
+<p>It seems your predicate is <em>always</em> "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>
@@ -72,7 +72,7 @@ an assigned value)!</p>
<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>rev(T, [RevTail|H])</code>? This forces the recursive call to
-<emph>return</emph> the head at the end of the list. But it doesn't know of this head, because you just
+<em>return</em> the head at the end of the list. But it doesn't know of this head, because you just
took it away! Inserting the head into the result, returned by the recursive call, is your job. To put it shortly,
insert <code>H</code> outside of the recursive call.</p>
''',
diff --git a/prolog/problems/lists_advanced/shiftleft_2/en.py b/prolog/problems/lists_advanced/shiftleft_2/en.py
index 6adbc12..9905cac 100644
--- a/prolog/problems/lists_advanced/shiftleft_2/en.py
+++ b/prolog/problems/lists_advanced/shiftleft_2/en.py
@@ -8,4 +8,60 @@ description = '''\
X = [2,3,4,5,1].
</pre>'''
-hint = {}
+plan = ['''\
+<p>I take the first element of a list, let's call it <code>H</code>, and add it <em>at the end</em> of
+the list's remainder (let's call the remainder <code>T</code>). As simple as that! You probably still
+remember how we took the last element of the list? Adding an element is the same operation as taking it,
+just from the opposite view ;)</p>
+''', '''\
+<p>A list of length one is represented as a pattern <code>[X]</code>. This might come in handy, as well
+as the predicate <code>conc/3</code>.</p>
+''', '''\
+<p>If the given list <code>L</code> is composed of head <code>H</code> and tail <code>T</code>, and if
+we add <code>H</code> at <em>the end</em> of <code>T</code>, then we get list <code>L</code>
+shifted left.</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>shiftleft/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>
+''',
+
+ '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>
+''',
+
+ 'conc_arg_not_list': '''\
+<p>All three arguments of predicate <code>conc/3</code> are <em>lists</em>.
+Are you sure you used it properly?</p>
+''',
+
+ 'arbitrary_result': '''\
+<p>Did you connect (use) all the variables? It seems as if you're returning an arbitrary result
+(a variable without an assigned value). It's usually not a good idea to ignore the warning about
+"singleton variables".</p>
+''',
+
+ 'tail_must_be_list': '''\
+<p>The list's tail is always another <em>list</em> and never an element!</p>
+''',
+}
diff --git a/prolog/problems/lists_advanced/shiftleft_2/sl.py b/prolog/problems/lists_advanced/shiftleft_2/sl.py
index aa83672..aa116ee 100644
--- a/prolog/problems/lists_advanced/shiftleft_2/sl.py
+++ b/prolog/problems/lists_advanced/shiftleft_2/sl.py
@@ -24,7 +24,7 @@ hint = {
'eq_instead_of_equ': '''\
<p>Operator <code>==</code> je strožji od operatorja <code>=</code> v smislu, da je za slednjega dovolj,
da elementa lahko naredi enaka (unifikacija). Morda z uporabo <code>=</code> narediš predikat
-<code>memb/2</code> delujoč tudi v kakšni drugi smeri.</p>
+<code>shiftleft/2</code> delujoč tudi v kakšni drugi smeri.</p>
<p>Seveda pa lahko nalogo rešiš brez obeh omenjenih operatorjev, spomni se, da lahko unifikacijo narediš
implicitno že kar v argumentih predikata (glavi stavka).</p>
''',
diff --git a/prolog/problems/lists_advanced/shiftright_2/en.py b/prolog/problems/lists_advanced/shiftright_2/en.py
index 4e0fec3..21b404d 100644
--- a/prolog/problems/lists_advanced/shiftright_2/en.py
+++ b/prolog/problems/lists_advanced/shiftright_2/en.py
@@ -8,4 +8,68 @@ description = '''\
X = [5,1,2,3,4].
</pre>'''
-hint = {}
+plan = ['''\
+<p>I take the last element from the given list and add it back at the start of the list's remainder.
+You probably still remember how we took the last element of the list? And adding an element at the start
+is quite simple, isn't it?</p>
+''', '''\
+<p>A list of length one is represented as a pattern <code>[X]</code>. This might come in handy, as well
+as the predicate <code>conc/3</code>.</p>
+''', '''\
+<p>If the given list <code>L</code> is composed of last element <code>E</code> and the remainder <code>L1</code>,
+and if we put <code>E</code> at <em>the start</em> of <code>L1</code>, then we get list <code>L</code>
+shifted right.</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>shiftleft/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>
+''',
+
+ '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>
+''',
+
+'conc_2nd_argument_not_1elem_list': '''\
+<p>Do you remember how the "pattern" representing a list with exactly one element looks like? Not like
+the second argument you gave to predicate <code>conc/3</code>. ;)</p>''',
+
+ 'arbitrary_result': '''\
+<p>Did you connect (use) all the variables? It seems as if you're returning an arbitrary result
+(a variable without an assigned value). It's usually not a good idea to ignore the warning about
+"singleton variables".</p>
+''',
+
+'shiftleftish_solution': '''\
+<p>The tail of the list is always another list and never just an element. How did you get the last
+element? This will not work...</p>''',
+
+'last_used': '''\
+<p>By using predicate <code>last/2</code> it will be difficult to solve this exercise as it leaves the last
+element in the original list. Rather try using predicate <code>conc/3</code> instead.</p>''',
+
+'final_hint': '''\
+<p>Predicates <code>shiftleft/2</code> and <code>shiftright/2</code> perform exactly the opposite function.
+If you simply swap the order of their arguments, you get the other predicate. In this way you could
+program <code>shiftright/2</code> just by calling <code>shiftleft/2</code>. You know that in prolog inputs
+and outputs can often be interchanged.</p>''',
+}
diff --git a/prolog/problems/lists_advanced/shiftright_2/sl.py b/prolog/problems/lists_advanced/shiftright_2/sl.py
index ce9b9fa..784f4ed 100644
--- a/prolog/problems/lists_advanced/shiftright_2/sl.py
+++ b/prolog/problems/lists_advanced/shiftright_2/sl.py
@@ -24,7 +24,7 @@ hint = {
'eq_instead_of_equ': '''\
<p>Operator <code>==</code> je strožji od operatorja <code>=</code> v smislu, da je za slednjega dovolj,
da elementa lahko naredi enaka (unifikacija). Morda z uporabo <code>=</code> narediš predikat
-<code>memb/2</code> delujoč tudi v kakšni drugi smeri.</p>
+<code>shiftright/2</code> delujoč tudi v kakšni drugi smeri.</p>
<p>Seveda pa lahko nalogo rešiš brez obeh omenjenih operatorjev, spomni se, da lahko unifikacijo narediš
implicitno že kar v argumentih predikata (glavi stavka).</p>
''',
diff --git a/prolog/problems/lists_advanced/sublist_2/en.py b/prolog/problems/lists_advanced/sublist_2/en.py
index 67b50a4..33e59c5 100644
--- a/prolog/problems/lists_advanced/sublist_2/en.py
+++ b/prolog/problems/lists_advanced/sublist_2/en.py
@@ -2,7 +2,7 @@ name = 'sublist/2'
slug = 'generate sublists of a list'
description = '''\
-<p><code>sublist(L, SL)</code>: <code>SL</code> is a continuous sublist of the
+<p><code>sublist(L, SL)</code>: <code>SL</code> is a continuous sublist of
list <code>L</code>. Your program should return every possible sublist; each
answer may be returned more than once.</p>
<pre>
@@ -16,4 +16,53 @@ answer may be returned more than once.</p>
X = [3].
</pre>'''
-hint = {}
+plan = ['''\
+<p>First a reminder: we're looking for sublists, not subsets. The difference is that sublists contain a number of
+<em>consecutive</em> elements of the original list.</p>
+<p>Perhaps you should look for some pattern? And which predicate is ideal to search for patterns?
+You already know that. ;)</p>
+''', '''\
+<p>Of course, predicate <code>conc/3</code> can be used to search for patterns in lists. Perhaps this time
+we don't even need explicite recursion? Is that really possible in prolog? ;)</p>
+''', '''\
+<p>So, what could the pattern be? Well, a part of the original list! Imagine that the original list is a tube
+that you want to shorten -- a little bit from the left, a little bit from the right -- what's left is a sublist!
+You chop off some elements from the front of the original list, and then you chop off some from the end.</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>sublist/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?</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>
+''',
+}
diff --git a/prolog/problems/lists_advanced/sublist_2/sl.py b/prolog/problems/lists_advanced/sublist_2/sl.py
index 4884665..b75aa0c 100644
--- a/prolog/problems/lists_advanced/sublist_2/sl.py
+++ b/prolog/problems/lists_advanced/sublist_2/sl.py
@@ -33,7 +33,7 @@ hint = {
'eq_instead_of_equ': '''\
<p>Operator <code>==</code> je strožji od operatorja <code>=</code> v smislu, da je za slednjega dovolj,
da elementa lahko naredi enaka (unifikacija). Morda z uporabo <code>=</code> narediš predikat
-<code>memb/2</code> delujoč tudi v kakšni drugi smeri.</p>
+<code>sublist/2</code> delujoč tudi v kakšni drugi smeri.</p>
<p>Seveda pa lahko nalogo rešiš brez obeh omenjenih operatorjev, spomni se, da lahko unifikacijo narediš
implicitno že kar v argumentih predikata (glavi stavka).</p>
''',
@@ -56,7 +56,7 @@ Do katerega elementa najlažje prideš?</p>
<p>Če je ime pravilno, se morda splača preveriti tudi, če se nisi zatipkal kje drugje,
je morda kakšna pika namesto vejice ali obratno, morda kakšna spremenljivka z malo začetnico?</p>
<p>Možno je seveda tudi, da so tvoji pogoji prestrogi ali celo nemogoči (kot bi bila npr. zahteva,
-da je <code>X</code> hkrati starš in sestra od <code>Y</code> ali kaj podobno zlobnega).</p>
+da je <code>N</code> enako kot <code>N + 1</code> ali kaj podobno logično zlobnega).</p>
''',
'timeout': '''\
diff --git a/prolog/problems/lists_advanced/sum_2/en.py b/prolog/problems/lists_advanced/sum_2/en.py
index 767a6f4..3abc348 100644
--- a/prolog/problems/lists_advanced/sum_2/en.py
+++ b/prolog/problems/lists_advanced/sum_2/en.py
@@ -2,10 +2,93 @@ 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 the list <code>L</code>.</p>
+<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>'''
-hint = {}
+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>
+''',
+}
diff --git a/prolog/problems/lists_advanced/sum_2/sl.py b/prolog/problems/lists_advanced/sum_2/sl.py
index 539271b..d3bddcf 100644
--- a/prolog/problems/lists_advanced/sum_2/sl.py
+++ b/prolog/problems/lists_advanced/sum_2/sl.py
@@ -22,7 +22,7 @@ hint = {
'eq_instead_of_equ': '''\
<p>Operator <code>==</code> je strožji od operatorja <code>=</code> v smislu, da je za slednjega dovolj,
da elementa lahko naredi enaka (unifikacija). Morda z uporabo <code>=</code> narediš predikat
-<code>memb/2</code> delujoč tudi v kakšni drugi smeri.</p>
+<code>sum/2</code> delujoč tudi v kakšni drugi smeri.</p>
<p>Seveda pa lahko nalogo rešiš brez obeh omenjenih operatorjev, spomni se, da lahko unifikacijo narediš
implicitno že kar v argumentih predikata (glavi stavka).</p>
''',
@@ -76,8 +76,8 @@ svoji levi strani.</p>
'forcing_result_onto_recursion': '''
<p>Ne vsiljuj rekurziji kaj naj vrne, prepusti se ji. To je tisti del, ko narediš predpostavko,
če je ta izpolnjena, potem bo tvoje pravilo delovalo za večji primer.</p>
-<p>Je tvoj rekurzivni klic oblike <code>len(T, LenT + H)</code>? S tem vsiljuješ rekurziji
-da mora <emph>vrniti</emph> vsoto celega seznama in ne samo repa. To ni v redu, za vrednost glave moraš ti povečati
+<p>Je tvoj rekurzivni klic oblike <code>sum(Tail, SumTail + H)</code>? S tem vsiljuješ rekurziji
+da mora vrniti vsoto <em>celega</em> seznama in ne samo repa. To ni v redu, za vrednost glave moraš ti povečati
rezultat, ki ti ga rekurzija vrne. Skratka, prištevanje naredi izven rekurzivnega klica.</p>
''',