summaryrefslogtreecommitdiff
path: root/prolog/problems
diff options
context:
space:
mode:
authorMartin Možina <martin.mozina@fri.uni-lj.si>2016-09-27 15:19:07 +0200
committerMartin Možina <martin.mozina@fri.uni-lj.si>2016-09-27 15:19:07 +0200
commit01eb98c7a5e86325e1243f0d0f4e111a18d1e535 (patch)
tree7871a2a0d30fd7761b6ac0f40846fbd004e10b25 /prolog/problems
parent5a00cf460426af73cb1fef953acf01f460887f77 (diff)
parent3bfcb3e651980f1675807b8f82826dcb3e4e1013 (diff)
Merge branch 'master' of 192.168.15.97:codeq-problems
Diffstat (limited to 'prolog/problems')
-rw-r--r--prolog/problems/lists/conc_3/en.py111
-rw-r--r--prolog/problems/lists/conc_3/sl.py10
-rw-r--r--prolog/problems/lists/del_3/en.py93
-rw-r--r--prolog/problems/lists/del_3/sl.py2
-rw-r--r--prolog/problems/lists/divide_3/en.py84
-rw-r--r--prolog/problems/lists/dup_2/en.py75
-rw-r--r--prolog/problems/lists/dup_2/sl.py2
-rw-r--r--prolog/problems/lists/insert_3/en.py82
-rw-r--r--prolog/problems/lists/insert_3/sl.py2
-rw-r--r--prolog/problems/lists/last_elem_2/en.py84
-rw-r--r--prolog/problems/lists/last_elem_2/sl.py2
-rw-r--r--prolog/problems/lists/memb_2/en.py68
-rw-r--r--prolog/problems/lists/permute_2/en.py77
-rw-r--r--prolog/problems/lists/permute_2/sl.py2
-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
-rw-r--r--prolog/problems/sorting/is_sorted_1/en.py81
-rw-r--r--prolog/problems/sorting/is_sorted_1/sl.py2
-rw-r--r--prolog/problems/sorting/isort_2/en.py55
-rw-r--r--prolog/problems/sorting/quick_sort_2/en.py59
-rw-r--r--prolog/problems/sorting/slowest_sort_ever_2/en.py44
38 files changed, 1597 insertions, 67 deletions
diff --git a/prolog/problems/lists/conc_3/en.py b/prolog/problems/lists/conc_3/en.py
index e25ae32..be32b7d 100644
--- a/prolog/problems/lists/conc_3/en.py
+++ b/prolog/problems/lists/conc_3/en.py
@@ -10,4 +10,113 @@ description = '''\
X = [1,2,3].
</pre>'''
-hint = {}
+plan = ['''\
+<p><img src="[%@resource plan.svg%]" /></p>
+''', '''\
+<p>Let's start with an easy question. What do I get if I concatenate an empty list and a list <code>L2</code>?</p>
+''', '''\
+<p>Now, assume that the first list has exactly one element. Let's temporarily take it out which leaves us
+with an empty list. But wait! Isn't this situation now similar to the one we dealt with before? Of course, we just
+reduced the problem into a smaller one (by one element smaller). Let recursion solve this smaller problem. Just don't
+forget to expand the recursion's result with the element you have taken out at the beginning...</p>
+''', '''\
+<p>Declarative/logic reasoning: Assume the first list <code>L1</code> has head <code>H</code> and tail
+<code>T</code>. If the recursive result of concatenating <code>T</code> and <code>L2</code> is some list
+<code>L3</code>, and if we add element <code>H</code> at the beginning of list <code>L3</code>, what do we get?
+A concatenation of <code>L1</code> and <code>L2</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>conc/3</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 is the simplest possible case?
+What's the answer if, for example, the first list is empty? (Just the first list should be empty,
+the second one can be arbitrary.)</p>
+''',
+
+ 'base_case_arbitrary': '''\
+<p>How can the result of concatenating two lists be an arbitrary list (a variable without an assigned value)?</p>
+<p>If your base case is similar to <code>conc([], L, _)</code>,
+then you should rethink it: what is the result of the concatenation, what do you return as the result?
+The base case <em>always</em> fully specifies the result, usually there are no unknowns (<code>_</code>
+or variables without assigned values) in what is being returned as the result.</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 an empty list <code>[]</code> is equal to a list with
+exactly three elements <code>[A,B,C]</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?
+Are you maybe reducing the first list, but your base case stops with an empty second list (or vice versa)?</p>
+''',
+
+ 'second_list_iteration': '''\
+<p>It seems you're processing (reducing) the second list. The mechanism at work is correct, however,
+the final ordering of the elements is not. It's better to process the first list in this way and
+leave the second one as is.</p>
+<p>There's another reason to process the first list: in this way the solution of this essential exercise
+will be the same for everyone, and we'll be able to use <code>conc/3</code> in a standardised way. This
+will be very important later on.</p>
+''',
+
+ 'insertion_into_second_list': '''
+<p>Is your recursive call of the form <code>conc(T, [H|L2], ...)</code>?
+Don't insert the first list's head into the second list as this will result in the wrong ordering
+of the elements. Let the recursion alone take care of concatenating the first list's tail
+<code>T</code> with the second list <code>L2</code>, and then, when returning the complete result,
+add the first list's head <code>H</code> into its proper place.</p>
+''',
+
+ 'two_heads': '''\
+<p>Do you really need two list heads? Are you trying to reduce both lists? This is not a good idea, it is
+difficult to solve the exercise in this way. Rather simply reduce the first list only, and leave the
+other list as is.</p>
+''',
+
+ 'two_heads_markup': '''\
+<p>Do you really need two list heads?</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>conc(T, L2, [H|...])</code>? This forces the recursive call to
+<em>return</em> the head at the start of the concatenated 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>
+''',
+
+ 'final_hint': '''\
+<p>Predicate <code>conc/3</code> will be useful for much more than just concatenating two lists.
+Among other things it can be used "in the other direction" -- for dividing a list into two parts. Try the
+following queries:</p>
+<p><code>?- conc(L1, L2, [a,b,c,d]).</code></p>
+<p><code>?- conc([X,Y], L2, [a,b,c,d,e,f]).</code></p>
+<p>Did you notice that the second query returned the first two elements from the list <code>[a,b,c,d,e,f]</code>?</p>
+<p>Furthermore, <code>conc/3</code> is useful to search for patterns in a list, e.g.:</p>
+<p><code>?- conc(_, [X,X|_], [a,b,c,c,d,e,f,f,g,h,h]).</code></p>
+<p>Right, this query finds all possibilities where two identical elements appear one after the other in a list
+(pattern X,X). Basically the query said that "there are some elements (possibly zero) in front, then follow two
+identical elements, and then again some elements (possibly zero) at the end."</p>
+<p>There are many other usages of <code>conc/3</code>, you will discover them along the way.</p>
+''',
+}
diff --git a/prolog/problems/lists/conc_3/sl.py b/prolog/problems/lists/conc_3/sl.py
index be2590e..5b0a639 100644
--- a/prolog/problems/lists/conc_3/sl.py
+++ b/prolog/problems/lists/conc_3/sl.py
@@ -92,8 +92,8 @@ res težko prišel do pravilne rešitve. Raje zmanjšuj samo prvi seznam in pust
'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>conc(T, L2 [H|...])</code>? S tem vsiljuješ rekurziji
-da mora <emph>vrniti</emph> tudi glavo, ki si jo prej že dal začasno stran. Glavo moraš na koncu na primerno mesto
+<p>Je tvoj rekurzivni klic oblike <code>conc(T, L2, [H|...])</code>? S tem vsiljuješ rekurziji
+da mora <em>vrniti</em> tudi glavo, ki si jo prej že dal začasno stran. Glavo moraš na koncu na primerno mesto
vstaviti ti. Skratka, glavo <code>H</code> dodaj izven rekurzivnega klica.</p>
''',
@@ -105,9 +105,9 @@ Med drugim je uporaben "v obratni smeri" za delitev seznama na dva dela, poskusi
<p>Si opazil, da je drugo vprašanje v bistvu vrnilo prva dva elementa iz seznama <code>[a,b,c,d,e,f]</code>?</p>
<p>Nadalje je <code>conc/3</code> uporaben za iskanje vzorcev v seznamu, npr. takole:</p>
<p><code>?- conc(_, [X,X|_], [a,b,c,c,d,e,f,f,g,h,h]).</code></p>
-<p>Tako je, to vprašanje najde vse možnosti, kjer se dva elementa ponovita drug za drugim v seznamu (vzorec X,X).
+<p>Tako je, to vprašanje najde vse možnosti, kjer se dva enaka elementa ponovita drug za drugim v seznamu (vzorec X,X).
V bistvu smo rekli "nekaj poljubnih elementov (lahko tudi nič) je spredaj, potem sta dva enaka, potem pa spet nekaj
-poljubnih elementov (lahko nič) zadaj."
-Še veliko drugih koristi bo od <code>conc/3</code>, jih boš že še sproti spoznal.</p>
+poljubnih elementov (lahko nič) zadaj."</p>
+<p>Še veliko drugih koristi bo od <code>conc/3</code>, jih boš že še sproti spoznal.</p>
''',
}
diff --git a/prolog/problems/lists/del_3/en.py b/prolog/problems/lists/del_3/en.py
index 99f87ca..d6e1e30 100644
--- a/prolog/problems/lists/del_3/en.py
+++ b/prolog/problems/lists/del_3/en.py
@@ -1,5 +1,5 @@
name = 'del/3'
-slug = 'delete an element from list'
+slug = 'delete element from list'
description = '''\
<p><code>del(X, L1, L2)</code>: the list <code>L2</code> is obtained from <code>L1</code> by deleting element <code>X</code>.</p>
@@ -15,4 +15,93 @@ description = '''\
X = 3, L = [1,2].
</pre>'''
-hint = {}
+plan = ['''
+<p style="text-align: center;">
+ <img style="display: inline-block; width: 40%; border-right: 1px solid lightgray;" src="[%@resource plan_a.svg%]" />
+ <img style="display: inline-block; width: 40%;" src="[%@resource plan_b.svg%]" />
+</p>
+<p>This exercise is very similar to the exercise <code>memb/2</code>, except that this time we also delete
+the element we are looking for. Where in the list can element <code>X</code> be hiding?
+Remember that a list has two parts: head and tail. Therefore there are two possibilies!</p>
+''', '''\
+<p>What is the simplest option? Perhaps deleting the first element?</p>
+''', '''\
+<p>How do I delete from the list's tail? Just divide the list into its head and tail, recursively (as
+the problem is one element smaller now) delete from the tail, and at the end don't forget about the
+head previously taken away.</p>
+''', '''\
+<p>Recursive step: if we assume <code>NewTail</code> is the tail with element <code>X</code> already deleted,
+then <code>[H|NewTail]</code> is the whole list with element <code>X</code> deleted.</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>del/3</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><img src="[%@resource base_case.svg%]" /></p>
+<p>Did you think of a base case? Where in the list is it the easiest to delete an 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 an empty list <code>[]</code> is equal to a list with
+exactly three elements <code>[A,B,C]</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>
+''',
+
+ 'del_from_empty_list_success': '''\
+<p>You can't delete an element from an empty list!</p>
+<p>If I delete an element from an empty list, this doesn't result in an empty list or anything else, but it
+simply shouldn't succeed. You don't even have to include a rule for this as prolog by default acts like that.
+You know how prolog loves to say "no"! :)</p>
+<p>If that is your base case, rethink it! Where in the list is it the easiest to delete an element?</p>
+''',
+
+ 'lost_heads': '''\
+<p><img src="[%@resource lost_heads.svg%]" /></p>
+<p>The element has been successfully deleted, but all the others before it got deleted too, right?
+Did you forget to put the head back at the front of the list after returning from recursion?</p>
+<p>Try asking the following query:</p>
+<p><code>?- del(d, [a,b,c,d,e,f,g], L).</code></p>
+''',
+
+ 'leading_heads_all_x': '''\
+<p><img src="[%@resource leading_heads_all_x.svg%]" /></p>
+<p>Did you forget (copy/paste?) and used <code>[X|T]</code> instead of the more general <code>[H|T]</code>
+in the recursive case?</p>
+<p>Of the following two queries one works and the other doesn't.</p>
+<p><code>?- del(d, [d,d,d,d,e,f,g], L).</code></p>
+<p><code>?- del(d, [a,b,c,d,e,f,g], L).</code></p>
+''',
+
+ 'final_hint': '''\
+<p>Interesting tidbit. Inserting and deleting an element into/from the list are opposite operations.
+Just by playing around with the arguments you can solve <code>del/3</code> using <code>insert/3</code>.</p>
+<p>Logically the following holds: deleting element <code>X</code> from list <code>BigList</code> resulting
+in list <code>SmallList</code> is the same as <em>inserting</em> element <code>X</code>
+into list <code>SmallList</code> to get list <code>BigList</code> as a result. ;)</p>
+''',
+}
diff --git a/prolog/problems/lists/del_3/sl.py b/prolog/problems/lists/del_3/sl.py
index feee5e4..17df017 100644
--- a/prolog/problems/lists/del_3/sl.py
+++ b/prolog/problems/lists/del_3/sl.py
@@ -97,7 +97,7 @@ Si pozabil dati glavo nazaj na začetek seznama, ko se vračaš iz rekurzije?</p
<p>Zanimivost: operaciji vstavljanja in brisanja iz seznama sta si ravno nasprotni. Če se malce poigraš z
argumenti, lahko <code>del/3</code> rešiš kar z <code>insert/3</code>.</p>
<p>Logično velja naslednje: če zbrišem <code>X</code> iz seznama <code>BigList</code> in dobim kot rezultat
-seznam <code>SmallList</code> je isto kot če <emph>vstavim</emph> <code>X</code> v seznam <code>SmallList</code> in dobim
+seznam <code>SmallList</code> je isto kot če <em>vstavim</em> <code>X</code> v seznam <code>SmallList</code> in dobim
kot rezultat seznam <code>BigList</code>. ;)</p>
''',
}
diff --git a/prolog/problems/lists/divide_3/en.py b/prolog/problems/lists/divide_3/en.py
index f4cfa82..f47a51b 100644
--- a/prolog/problems/lists/divide_3/en.py
+++ b/prolog/problems/lists/divide_3/en.py
@@ -1,5 +1,5 @@
name = 'divide/3'
-slug = 'split a list into parts of roughly equal length'
+slug = 'split a list into two parts of roughly equal length'
description = '''\
<p><code>divide(L, L1, L2)</code>: the list <code>L1</code> contains elements at odd positions in <code>L</code>, and the list <code>L2</code> contains the elements at even positions in <code>L</code>.</p>
@@ -10,4 +10,84 @@ description = '''\
X = [a,c,e], Y = [b,d,f].
</pre>'''
-hint = {}
+plan = ['''\
+<p><img src="[%@resource plan.svg%]" /></p>
+<p>You know... first, second, first, second, ...</p>
+''', '''\
+<p>Can you pick two heads from the list's beginning? The pattern is <code>[H1,H2|T]</code>.</p>
+''', '''\
+<p>You take two elements from the list's beginning, the rest is recursively split, and then you
+accordingly add those two elements into the recursion's result. By taking the two elements out,
+you reduce (simplify) the problem and thus enable the recursion.</p>
+''', '''\
+<p>If we assume the recursion splits the tail <code>T</code> into lists <code>L1</code> and <code>L2</code>,
+and upon returning the result we add <code>H1</code> at the start of <code>L1</code> and <code>H2</code>
+at the start of <code>L2</code>, then we get the split of the initial list of the form <code>[H1,H2|T]</code>
+into two approximately equal parts.</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? What's the simplest possible case? What if the list is empty?</p>
+''',
+
+ 'base_case_arbitrary': '''\
+<p>How can the result of splitting a list be an arbitrary list(s) or an unassigned variable(s)?</p>
+<p>If your base case is reminiscent of <code>divide([], _, _)</code> or <code>divide([X], [X|_], ...)</code>,
+rethink it! What should be the result of splitting? The base case <em>always</em> fully specifies the result,
+usually there are no unknowns (<code>_</code> or variables without assigned values) in what is being
+returned as the result.</p>
+''',
+
+ 'second_base_case_missing': '''\
+<p>The recursion doesn't always succeed. Are there perhaps two different cases how it could end? You know,
+odd and even ;) Do you need an extra base case? Try the following two queries; one will succeed, and the
+other will fail.</p>
+<p><code>?- divide([a,b,c], L1, L2).</code></p>
+<p><code>?- divide([a,b,c,d], L1, L2).</code></p>
+''',
+
+ 'unsuccessful_conc_use': '''\
+<p>Are you using <code>conc/3</code>? This is probably not a good idea here as <code>conc/3</code>
+splits the list in "blocks" and not on an element-by-element level. Rather try without it.</p>
+''',
+
+ 'forcing_result_onto_recursion': '''
+<p>Don't force the result onto recursion, don't tell it what it should return. Just let it be and
+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>divide(T, [H1|...], [H2|...])</code>? This forces the recursive call
+to also <em>return</em> both heads that it <em>doesn't know of</em> since you previously took them away.
+Adding those heads to the result, returned by the recursive call, is your job. To put it shortly,
+add elements <code>H1</code> and <code>H2</code> outside the recursive call.</p>
+''',
+
+ 'recursive_case': '''\
+<p>The base cases are 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 an empty list <code>[]</code> is equal to a list with
+exactly three elements <code>[A,B,C]</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/dup_2/en.py b/prolog/problems/lists/dup_2/en.py
index 3639683..e944f74 100644
--- a/prolog/problems/lists/dup_2/en.py
+++ b/prolog/problems/lists/dup_2/en.py
@@ -10,4 +10,77 @@ description = '''\
X = [1,1,2,2,3,3].
</pre>'''
-hint = {}
+plan = ['''
+<p><img src="[%@resource plan.svg%]" /></p>
+<p>This is an exercise in classic recursion. Let's be brave and assume that we already have
+a duplicated tail of the list. Then all we need to do is to duplicate the head (H becomes H, H) and
+add this at the start of the duplicated tail.</p>
+''', '''\
+<p>A base case must be elementary, right? What if the list doesn't contain any elements at all,
+what is the result in this case?</p>
+''', '''\
+<p>If we have a duplicated tail <code>DT</code> and put two heads <code>[H, H]</code> in front of it,
+then that is exactly the duplicated list.</p>
+<p>And how do we get the duplicated tail? Since the tail is smaller than the whole list,
+we can use recursion on it!</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>dup/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_missing_[]': '''\
+<p>Your base case makes perfect sense, but it doesn't work for a very specific case: an empty list.
+Tweak it a little bit. However, don't write two base cases, because that will result in a new problem:
+the (albeit correct) solutions will all be repeated twice.</p>
+''',
+
+ 'base_case_arbitrary': '''\
+<p>How can the result of duplicating an empty list be an arbitrary list or an unassigned variable?
+As the mathematicians would say: "Two times zero is zero and not just anything!"</p>
+<p>If your base case is <code>dup([], _).</code>, rethink it! What is the result of
+duplicating the elements of an empty list?</p>
+''',
+
+ 'base_case': '''\
+<p>Did you think of a base case? Which list is the easiest to "duplicate"?</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 an empty list <code>[]</code> is equal to a list with
+exactly three elements <code>[A,B,C]</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>
+''',
+
+ '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>dup(T, [H,H|...])</code>? This forces the recursive call to
+<em>return</em> the duplicated head at the start of the list. But it doesn't know of this head, because you just
+took it away! Adding the duplicated head to the result, returned by the recursive call, is your job.
+To put it shortly, add the duplicated <code>H</code> outside of the recursive call.</p>
+''',
+}
diff --git a/prolog/problems/lists/dup_2/sl.py b/prolog/problems/lists/dup_2/sl.py
index 0358726..b1492c5 100644
--- a/prolog/problems/lists/dup_2/sl.py
+++ b/prolog/problems/lists/dup_2/sl.py
@@ -71,7 +71,7 @@ da je <code>X</code> hkrati starš in sestra od <code>Y</code> ali kaj podobno z
<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>dup(T, [H,H|...])</code>? S tem vsiljuješ rekurziji
-da mora <emph>vrniti</emph> tudi podvojeno glavo. To moraš narediti ti z (obdelanim) rezultatom, ki ga rezurzija vrne.
+da mora <em>vrniti</em> tudi podvojeno glavo. To moraš narediti ti z (obdelanim) rezultatom, ki ga rezurzija vrne.
Skratka, [H,H] dodaj izven rekurzivnega klica.</p>
''',
}
diff --git a/prolog/problems/lists/insert_3/en.py b/prolog/problems/lists/insert_3/en.py
index 5553445..f0a3e4a 100644
--- a/prolog/problems/lists/insert_3/en.py
+++ b/prolog/problems/lists/insert_3/en.py
@@ -10,4 +10,84 @@ description = '''\
L = [2,3,1].
</pre>'''
-hint = {}
+plan = ['''
+<p><img src="[%@resource plan.svg%]" /></p>
+<p>Where in the list can we insert a new element <code>X</code>? Remember that a list has two parts: head and tail.
+That means there are two possibilies. That's right, only two -- but in the tail we can again insert either as its
+new head or into the tail of the tail. And so on. Recursion to the rescue!</p>
+''', '''\
+<p>What is the simplest option? Insert at the beginning!</p>
+''', '''\
+<p>How do I insert into the list's tail? Just divide the list into its head and tail, recursively (as
+the problem is one element smaller now) insert into the tail, and at the end don't forget about the
+head previously taken away.</p>
+''', '''\
+<p>Recursive step: if we assume <code>NewTail</code> is the tail with already inserted element <code>X</code>,
+then <code>[H|NewTail]</code> is the whole list with element <code>X</code> inserted.</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>insert/3</code> more general (e.g. able to work with output arguments becoming inputs).
+This might come in handy later on!</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><img src="[%@resource base_case.svg%]" /></p>
+<p>Did you think of a base case? In which place in the list is it the easiest to insert a new 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 an empty list <code>[]</code> is equal to a list with
+exactly three elements <code>[A,B,C]</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>
+''',
+
+ 'ins_results_in_empty_list': '''\
+<p>How can the result of the insertion be an empty list?</p>
+<p>If that is your base case, rethink it! What is the result of the insertion?</p>
+''',
+
+ 'ins_results_in_arbitrary_result': '''\
+<p>How can the result of the insertion be an arbitrary list or an unassigned variable?</p>
+<p>If that is your base case, rethink it! What is the result of the insertion?</p>
+''',
+
+ 'lost_heads': '''\
+<p><img src="[%@resource lost_heads.svg%]" /></p>
+<p>The element has been successfully inserted, but all the others before it are lost, right?
+Did you forget to put the head back at the front of the list after returning from recursion?</p>
+<p>Try asking the following query and check <em>all</em> the solutions:</p>
+<p><code>?- insert(q, [a,b,c,d], L).</code></p>
+''',
+
+ 'leading_heads_all_x': '''\
+<p><img src="[%@resource leading_heads_all_x.svg%]" /></p>
+<p>Did you forget (copy/paste?) and used <code>[X|T]</code> instead of the more general <code>[H|T]</code>
+in the recursive case?</p>
+<p>Of the following two queries one works and the other doesn't.</p>
+<p><code>?- insert(d, [d,d,d,d,e,f,g], L).</code></p>
+<p><code>?- insert(d, [a,b,c,d,e,f,g], L).</code></p>
+''',
+}
diff --git a/prolog/problems/lists/insert_3/sl.py b/prolog/problems/lists/insert_3/sl.py
index 17efb5b..7f62f7e 100644
--- a/prolog/problems/lists/insert_3/sl.py
+++ b/prolog/problems/lists/insert_3/sl.py
@@ -74,7 +74,7 @@ da je <code>X</code> hkrati starš in sestra od <code>Y</code> ali kaj podobno z
<p><img src="[%@resource lost_heads.svg%]" /></p>
<p>Element je vstavljen, ampak vsi pred njim so se pa izgubili, kajne?
Si pozabil dati glavo nazaj na začetek seznama, ko se vračaš iz rekurzije?</p>
-<p>Poskusi postaviti naslednje vprašanje prologu in preglej <emph>vse</emph> rešitve:</p>
+<p>Poskusi postaviti naslednje vprašanje prologu in preglej <em>vse</em> rešitve:</p>
<p><code>?- insert(q, [a,b,c,d], L).</code></p>
''',
diff --git a/prolog/problems/lists/last_elem_2/en.py b/prolog/problems/lists/last_elem_2/en.py
index 93c7c05..5eec3b8 100644
--- a/prolog/problems/lists/last_elem_2/en.py
+++ b/prolog/problems/lists/last_elem_2/en.py
@@ -10,4 +10,86 @@ description = '''\
X = 1.
</pre>'''
-hint = {}
+plan = ['''\
+<p>It's easy to access the first element in a list, but to get to the last element one needs to
+recursively go through the whole list.</p>
+''', '''\
+<p>The list can be divided into its head and tail, and the search can proceed with the tail.
+The problem is now smaller (the tail is shorter than the whole list), so we can use recursion.</p>
+''', '''\
+<p>If <code>X</code> is the last element of tail <code>T</code>, then <code>X</code> is also
+the last element of the whole list that looks like <code>[H|T]</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>last_elem/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 simplest possible case? What if the list contains only one element?</p>
+''',
+
+ '[]_should_not_succeed': '''\
+<p>How did you succeed to find a last element in an empty list? You likely need a different base case.</p>
+''',
+
+ 'list_returned': '''\
+<p>You are returning a list instead of an element.</p>
+''',
+
+ 'clumsy_conc_use': '''\
+<p>Are you using <code>conc/3</code>? An interesting idea. Don't forget that the second list you're
+concatenating must be <em>of length one</em> if you want to achieve the desired effect.
+So a pattern of the form <code>[X]</code>, right?</p>
+''',
+
+ 'unsuccessful_conc_use': '''\
+<p>Are you using <code>conc/3</code>? An interesting idea; it is possible to solve in this way.
+However, a bit of tweaking is still needed. Don't forget that <code>conc/3</code> has three arguments,
+and all three are lists. Think about what kind of a pattern do you need...</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 an empty list <code>[]</code> is equal to a list with
+exactly three elements <code>[A,B,C]</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>
+''',
+
+ 'final_hint': '''\
+<p>Interesting fact: predicate <code>conc/3</code> can be used to search for patterns in lists. The last
+element in a list is also a kind of pattern. What happens if we concatenate an arbitrary list <code>_</code>
+and a list <em>of length one</em> (in this order)? A list of length one is of course written as
+<code>[Element]</code>.</p>
+<p>Try asking the following query:</p>
+<p><code>?- conc(_, [Element], [a,b,c,d,e,f,q]).</code></p>
+<p>So, can you now fetch the list's last element using <code>conc/3</code>? This will be very useful in
+further exercises. On the other hand, of course, accessing the last element of a list is still quite
+expensive, it's done in O(n) time. Therefore, if it's not important which element of a list is to be used,
+or where in a list a new element is to be added, always work with the head.</p>
+<p>And what does this query do? ;)</p>
+<p><code>?- conc([a,b,c], [q], L).</code></p>
+''',
+}
diff --git a/prolog/problems/lists/last_elem_2/sl.py b/prolog/problems/lists/last_elem_2/sl.py
index afba57a..961963c 100644
--- a/prolog/problems/lists/last_elem_2/sl.py
+++ b/prolog/problems/lists/last_elem_2/sl.py
@@ -47,7 +47,7 @@ implicitno že kar v argumentih predikata (glavi stavka).</p>
'clumsy_conc_use': '''\
<p>Uporabljaš <code>conc/3</code>? Zanimiva ideja. Ne pozabi, da mora drugi seznam, ki ga konkateniraš
-biti dolžine ena, če hočeš doseči to kar želiš. Torej vzorec oblike <code>[X]</code>, kajne?</p>
+biti <em>dolžine ena</em>, če hočeš doseči to kar želiš. Torej vzorec oblike <code>[X]</code>, kajne?</p>
''',
'unsuccessful_conc_use': '''\
diff --git a/prolog/problems/lists/memb_2/en.py b/prolog/problems/lists/memb_2/en.py
index ae62825..681c18a 100644
--- a/prolog/problems/lists/memb_2/en.py
+++ b/prolog/problems/lists/memb_2/en.py
@@ -12,4 +12,70 @@ description = '''\
X = 1.
</pre>'''
-hint = {}
+plan = ['''\
+<p>Where can we find the searched for element <code>X</code>? Remember that the list has two parts: the head and
+the tail. Therefore, there are two possibilies! ;)</p>
+''', '''\
+<p><img src="[%@resource base_case.svg%]" /></p>
+<p>In prolog we can understand a list like a queue of people waiting for a bus. The driver only sees
+the first person in the queue, the others are hidden in the list's tail. So the element <code>X</code>
+can either be at the start of the queue or...</p>
+''', '''\
+<p>It's easy to look at ("search for") the head of the list. But how do we search the tail? Simply,
+we remove the first element and repeat the search with the smaller list (tail). If <code>[H|T]</code>
+is our whole list, then <code>T</code> is this same list without the first element.
+Since the new list (tail) is smaller, we reduced the problem and thus facilitated the use of recursion.</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>memb/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><img src="[%@resource base_case.svg%]" /></p>
+<p>Did you think of a base case? What is the simplest possible case if the element is present in the list?
+Which element in the list is the easiest to access?</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 an empty list <code>[]</code> is equal to a list with
+exactly three elements <code>[A,B,C]</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>
+''',
+
+ 'final_hint': '''\
+<p>Predicate <code>memb/2</code> is useful for much more than just checking whether a list contains
+a given element or not. Actually, most of the time, it's used in "a different direction" as
+"return some element <code>X</code> from list <code>L</code>". In fact you've just written yourself
+a generator of elements from the list.</p>
+<p>Try the following query:</p>
+<p><code>?- memb(Coin, [1,2,5,10,20,50,100,200]).</code></p>
+<p>or this one:</p>
+<p><code>?- memb(Operator, [+, -, *, /]).</code></p>
+<p>Can you form a query to ask prolog how do we get a sum of 30 cents with exactly three coins?
+The operator <code>=:=</code> is used to check for arithmetic equality. How many solutions are there? ;)</p>
+''',
+}
diff --git a/prolog/problems/lists/permute_2/en.py b/prolog/problems/lists/permute_2/en.py
index 201d8d6..ba20d67 100644
--- a/prolog/problems/lists/permute_2/en.py
+++ b/prolog/problems/lists/permute_2/en.py
@@ -13,4 +13,79 @@ description = '''\
L = [3,2,1].
</pre>'''
-hint = {}
+plan = ['''\
+<p><img src="[%@resource plan.svg%]" /></p>
+<p>Try recursively constructing one possibility, but leave prolog its freedom. It will then return
+all the possibilities by itself.</p>
+''', '''\
+<p>There are several options, one goes like this: if I take away the head, this reduces the problem and I can
+leave it to recursion, and at the end I put the head back. Where do I put the head? I insert it in
+<em>all</em> possible places, one solution at a time.</p>
+''', '''\
+<p>If I assume the recursion permutes the tail <code>T</code> into the "permutated tail"
+<code>PT</code> and then I insert head <code>H</code> somewhere into <code>PT</code>, then I will get
+some permutation of the initial list <code>[H|T]</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).</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 most elementary case? What if the list is empty?</p>
+''',
+
+ 'base_case_arbitrary': '''\
+<p>How can the result of permutating a list be an arbitrary list or an unassigned variable?</p>
+<p>If your base case is reminiscent of <code>permute([], _)</code>, rethink it!
+What should be the result of permutating a list?
+The base case <em>always</em> fully specifies the result, usually there are no unknowns (<code>_</code>
+or variables without assigned values) in what is being returned as the result.</p>
+''',
+
+ 'unsuccessful_conc_use': '''\
+<p>Are you using <code>conc/3</code>? It's probably not so useful to solve this exercise,
+but the solution to some other previous exercise might be what is required.</p>
+''',
+
+ 'forcing_result_onto_recursion': '''
+<p>Don't force the result onto recursion, don't tell it what it should return. Just let it be and
+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>permute(T, [H|...])</code>? This forces the recursive call to
+also <em>return</em> the head <code>H</code> which it <em>doesn't know of</em> since you previously 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>
+''',
+
+ 'recursive_case': '''\
+<p>The base case is ok. However, what about the general recursive case?</p>
+''',
+
+ 'no_insert_or_delete': '''\
+<p>The base case is ok. However, what about the general recursive case? Perhaps it's a good idea
+to reuse some previous exercise?</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 an empty list <code>[]</code> is equal to a list with
+exactly three elements <code>[A,B,C]</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/permute_2/sl.py b/prolog/problems/lists/permute_2/sl.py
index 8cd11e9..ccf4cd7 100644
--- a/prolog/problems/lists/permute_2/sl.py
+++ b/prolog/problems/lists/permute_2/sl.py
@@ -59,7 +59,7 @@ rešena naloga.</p>
<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>permute(T, [H|...])</code>? S tem vsiljuješ rekurziji
-da mora <emph>vrniti</emph> tudi glavo, ki je sploh ne pozna, ker si jo ravnokar vzel stran! To moraš
+da mora <em>vrniti</em> tudi glavo, ki je sploh ne pozna, ker si jo ravnokar vzel stran! To moraš
narediti ti z rezultatom, ki ga rekurzija vrne. Skratka, element <code>H</code> dodaj izven rekurzivnega klica.</p>
''',
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>
''',
diff --git a/prolog/problems/sorting/is_sorted_1/en.py b/prolog/problems/sorting/is_sorted_1/en.py
index 8741bc7..678494c 100644
--- a/prolog/problems/sorting/is_sorted_1/en.py
+++ b/prolog/problems/sorting/is_sorted_1/en.py
@@ -10,4 +10,83 @@ description = '''\
false.
</pre>'''
-hint = {}
+plan = ['''\
+<p>As always try to reduce the problem onto a smaller one. Do an appropriate check (comparison) at
+the start of the list, and submit the tail to a recursive check.</p>
+''', '''\
+<p>You do know how to access the first <em>two</em> elements of the list, right? And the arithmetic comparison
+operators were introduced in the previous batch of exercises.</p>
+''', '''\
+<p>If the given list <code>L</code> is composed of heads <code>H1</code> and <code>H2</code> and of tail
+<code>T</code>, and if we assume that tail <code>T</code> along with the second head is sorted, and furthermore
+<code>H1</code> is smaller or equal to <code>H2</code>, then the whole list <code>L</code> is sorted.</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 is one of the shortest sorted lists?</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>X</code> is <em>simultaneously</em> smaller and greater than
+<code>Y</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>
+''',
+
+ '[]_base_case_missing': '''\
+<p>For completeness, please take care of the special case, i.e. the empty list which is also sorted.
+But be careful not to destroy the other solutions.</p>
+''',
+
+ 'duplicates_fail': '''\
+<p>Did you forget about duplicate elements? The list below is also sorted!</p>
+<p><code>?- is_sorted([25,25,25,25]).</code></p>
+''',
+
+ 'H1_instead_of_H2_sent_into_recursion': '''\
+<p>Did you send the wrong of the two list heads into recursion?</p>
+''',
+
+ 'base_case_at_len_1_missing': '''\
+<p>The recursive case in this exercise requires two elements, even though you put one back when the tail
+is recursively processed. But what happens when there is just a single element left in the list? Think
+about it as this will probably be the main base case.</p>
+''',
+
+ 'both_heads_omitted_from_recursion': '''\
+<p>Are you taking two elements out of the list before initiating a recursive call? You're trying to
+reduce the number of comparisons, aren't you? ;) But unfortunately this will not be possible! Of the following
+two cases below one works correctly and one doesn't. What's the difference between them?</p>
+<p><code>?- is_sorted([1,3,14,16,24,25]).</code></p>
+<p><code>?- is_sorted([24,25,14,16,1,3]).</code></p>
+''',
+
+ 'min_used': '''\
+<p>Try solving this exercise without using the predicate <code>min/2</code>. Your solution should have the
+time complexity of O(n). By using <code>min/2</code> the complexity is typically about O(n*n).</p>
+''',
+}
diff --git a/prolog/problems/sorting/is_sorted_1/sl.py b/prolog/problems/sorting/is_sorted_1/sl.py
index de52984..36ace61 100644
--- a/prolog/problems/sorting/is_sorted_1/sl.py
+++ b/prolog/problems/sorting/is_sorted_1/sl.py
@@ -77,7 +77,7 @@ glavni robni pogoj!</p>
'both_heads_omitted_from_recursion': '''\
<p>Jemlješ po dva elementa iz seznama preden greš v rekurzijo? Poskušaš malce prihraniti pri primerjavah, kajne? ;)
-Ampak žal to ne gre! Od spodnjih dveh primerov eden deluje pravilno in eden ne, ugotovi v čem je razlika. </p>
+Ampak žal to ne gre! Od spodnjih dveh primerov eden deluje pravilno in eden ne, ugotovi v čem je razlika.</p>
<p><code>?- is_sorted([1,3,14,16,24,25]).</code></p>
<p><code>?- is_sorted([24,25,14,16,1,3]).</code></p>
''',
diff --git a/prolog/problems/sorting/isort_2/en.py b/prolog/problems/sorting/isort_2/en.py
index 71b1a12..35beb62 100644
--- a/prolog/problems/sorting/isort_2/en.py
+++ b/prolog/problems/sorting/isort_2/en.py
@@ -8,4 +8,57 @@ description = '''\
L = [1,2,3,4,5].
</pre>'''
-hint = {}
+plan = ['''\
+<p>When going through the list (actually when returning from recursion) at every step insert the current element
+in its proper position.</p>
+''', '''\
+<p>When going through the list at every step take away the head (it's stored on stack), while its tail goes
+into recursion (the problem/list is shorter, so this is possible). The recursion returns the <em>sorted</em>
+tail, and all that's left for you to do is to put the previously taken away head into its proper place in the
+sorted tail. Of course you can reuse some previous exercise for this task.</p>
+''', '''\
+<p>If list <code>L</code> is composed of head <code>H</code> and tail <code>T</code> and if we assume that
+tail <code>T</code> is correctly sorted into <code>SortedTail</code> by recursion, and if head <code>H</code>
+is inserted into its proper place within <code>SortedTail</code>, then we get the whole list <code>L</code>
+properly sorted.</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 can you sort without any effort whatsoever?</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>X</code> is <em>simultaneously</em> smaller and greater than
+<code>Y</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>
+''',
+
+ 'min_used': '''\
+<p>Try solving this exercise without using the predicate <code>min/2</code>.</p>
+''',
+}
diff --git a/prolog/problems/sorting/quick_sort_2/en.py b/prolog/problems/sorting/quick_sort_2/en.py
index aa3eb44..a5b571b 100644
--- a/prolog/problems/sorting/quick_sort_2/en.py
+++ b/prolog/problems/sorting/quick_sort_2/en.py
@@ -8,4 +8,61 @@ description = '''\
L = [1,2,3,4,5].
</pre>'''
-hint = {}
+plan = ['''\
+<p>Divide and conquer! And use previous solutions, of course. :)</p>
+''', '''\
+<p>Take the head away, use it as a pivot, divide the tail into smaller and larger elements. Use recursion on
+so obtained sublists since both are shorter (in the worst case scenario shorter by just the head element --
+this also explains why quicksort works worst on already sorted lists). In the end simply combine the sublists.</p>
+''', '''\
+<p>If list <code>L</code> is composed of head <code>P</code> and tail <code>T</code> and if the tail is
+split into sublists containing smaller and larger elements, respectively, based on pivot <code>P</code>, and if
+we assume the recursion sorts these two sublists into lists <code>SortedSmallerElems</code> and
+<code>SortedGreaterElems</code>, and if finally we concatenate these two lists and add in between pivot/head
+<code>P</code>, then this results in correctly sorted initial list <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).</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 can you sort without any effort whatsoever?</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>X</code> is <em>simultaneously</em> smaller and greater than
+<code>Y</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>How can the sorted list be anything whatsoever or a list with an arbitrary element? Did you use
+a variable without an assigned value?</p>
+''',
+
+ 'forgotten_pivot': '''\
+<p>Did you, perhaps, forgot to put the pivot element back into the list when returning from recursion?</p>
+''',
+}
diff --git a/prolog/problems/sorting/slowest_sort_ever_2/en.py b/prolog/problems/sorting/slowest_sort_ever_2/en.py
index 0e359b4..72a70bb 100644
--- a/prolog/problems/sorting/slowest_sort_ever_2/en.py
+++ b/prolog/problems/sorting/slowest_sort_ever_2/en.py
@@ -8,4 +8,46 @@ description = '''\
L = [1,2,3,4,5].
</pre>'''
-hint = {}
+plan = ['''\
+<p>This exercise is mostly for fun... all you need are two lines, i.e. two prolog goals.</p>
+''', '''\
+<p>Perhaps you can reuse some previous solutions?</p>
+''', '''\
+<p>Which of the previous solutions has time complexity of O(n!)? Use it!</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>
+''',
+
+ '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>X</code> is <em>simultaneously</em> smaller and greater than
+<code>Y</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>
+''',
+
+ 'no_permute': '''\
+<p>Hmmm, which of the previous exercises has time complexity of O(n!)? How can you use it here?</p>
+''',
+
+ 'no_isSorted': '''\
+<p>You're on the right path, just a bit more to go. Perhaps you can reuse another previous exercise?</p>
+''',
+}