summaryrefslogtreecommitdiff
path: root/prolog/problems/lists/dup_2/sl.py
blob: ccb0b1df2cb68ed8cebb828cfc0a0aa19bcebb66 (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
# coding=utf-8

name = 'dup/2'
slug = 'Podvoji vse elemente v seznamu'

description = '''\
<p><code>dup(L1, L2)</code>: seznam <code>L2</code> dobimo iz <code>L1</code> tako, da podvojimo vsak 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>Klasična rekurzivna naloga. Bodimo pogumni in privzemimo, da že imamo podvojen rep seznama.
Potem je vse kar moramo še storiti to, da podvojimo glavo (H postane H, H) in to dodamo pred
podvojen rep.</p>
''', '''\
<p>Robni pogoj mora biti enostaven, kajne? Kaj, če seznam sploh nima elementov, kaj je potem rezultat?</p>
''', '''\
<p>Če imam podvojen rep <code>DT</code> in pred to postavim dve glavi <code>[H, H]</code>,
potem je to skupaj ravno podvojen seznam.</p>
<p>Kako pa dobim podvojen rep? Rep je manjši od celega seznama, zato si lahko privoščim rekurzijo!</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 prilagodi (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>
''',

    'eq_instead_of_equ_markup': '''\
<p>Morda bi šlo brez tega?</p>
''',

    'base_case_missing_[]': '''\
<p>Tvoj robni pogoj je sicer smiselen, a ne deluje za poseben primer: prazen seznam. Malce ga predelaj.
Ne naredi pa dveh robnih pogojev, ker bo to prineslo nov problem: pravilne rešitve se bodo podvajale.</p>
''',

    'base_case_arbitrary': '''\
<p>Kako je lahko rezultat podvajanja praznega seznama poljuben seznam oz. karkoli?
Matematiki bi rekli: "Dvakrat nič je nič in ne karkoli."</p>
<p>Če je tvoj robni pogoj <code>dup([], _).</code>, ga še enkrat premisli: kaj je rezultat podvajanja?</p>
''',

    'base_case': '''\
<p>Si pomislil na robni pogoj? Kakšen seznam najlažje "podvojiš"?</p>
''',

    'recursive_case': '''\
<p>Robni primer deluje. Kaj pa rekurzivni, splošni, primer?</p>
''',

    'predicate_always_false': '''\
<p>Vse kaže, da tvoj predikat vedno vrne "false". Si mu dal pravilno ime, si se morda pri imenu zatipkal?</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>
''',

    'timeout': '''\
<p>Je morda na delu potencialno neskončna rekurzija? Kako se bo ustavila?</p>
<p>Morda pa je kriv tudi manjkajoč, neustrezen ali preprosto nekompatibilen (s splošnim primerom) robni pogoj?</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>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.
Skratka, [H,H] dodaj izven rekurzivnega klica.</p>
''',
}