summaryrefslogtreecommitdiff
path: root/prolog/problems/lists/divide_3/en.py
blob: f47a51b124f1af47b8a0e2b506343d6075d7d712 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
name = 'divide/3'
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>
<pre>
?- divide([a,b,c,d,e,f,g], X, Y).
  X = [a,c,e,g], Y = [b,d,f].
?- divide([a,b,c,d,e,f], X, Y).
  X = [a,c,e], Y = [b,d,f].
</pre>'''

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