1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
name = 'rev/2'
slug = 'reverse a list'
description = '''\
<p><code>rev(L1, L2)</code>: the list <code>L2</code> is obtained from <code>L1</code> by reversing the order of the elements.</p>
<pre>
?- rev([1,2,3], X).
X = [3,2,1].
?- rev([], X).
X = [].
</pre>'''
plan = ['''\
<p>This is one of the most rewarding exercises. Classic recursion! Try to reduce the problem into a smaller one.
That, of course, means reducing it to a shorter list.</p>
''', '''\
<p>I divide the list into its head and tail, the recursion reverses the tail, and all I have to do
is to insert the head into its proper location in the reversed tail.</p>
''', '''\
<p>If the given list <code>L</code> is composed of head <code>H</code> and tail <code>T</code>
and if I assume the recursion reverses tail <code>T</code> into reversed tail <code>RT</code> and if I add head
<code>H</code> at the end of <code>RT</code>, then the result is reversed 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). 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>
''',
'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 most trivial to reverse?</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>
''',
'base_case_at_len1': '''\
<p>Your base case is perfectly reasonable, but it doesn't work for an empty list.
However, don't use two base cases here, because this will duplicate the solutions./p>
''',
'arbitrary_base_case': '''\
<p>What is the result of reversing an empty list? Surely not an arbitrary list (a variable without
an assigned value)!</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>rev(T, [RevTail|H])</code>? This forces the recursive call to
<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>
''',
'using_other_solutions': '''\
<p>Predicates <code>last/2</code>, <code>shiftleft/2</code>, or <code>shiftright/2</code> will not be of
much help here. Rather try without them, it will be easier.</p>
''',
'insertion_at_beginning': '''\
<p>Did you insert the head at <em>the start</em> of the reversed tail? That's not its proper place; in this way
you just reassemble the original list.</p>
''',
'invalid_insert_at_end': '''\
<p>Remember, a list's tail is always another list, not an element.
How do you insert an element at the end of the list?</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>
''',
}
|