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

description = '''\
<p><code>dup(L1, L2)</code>: the list <code>L2</code> is obtained from <code>L1</code> by duplicating every element.</p>
<pre>
?- dup([1,2], X).
  X = [1,1,2,2].
?- dup([1,2,3], X).
  X = [1,1,2,2,3,3].
</pre>'''

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>
''',
}