summaryrefslogtreecommitdiff
path: root/prolog/problems/lists/del_3/sl.py
blob: feee5e49061f834c65f0e10de69ada31e5cf407f (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
94
95
96
97
98
99
100
101
102
103
name = 'del/3'
slug = 'Zbriši element iz seznama'

description = '''\
<p><code>del(X, L1, L2)</code>: seznam <code>L2</code> dobimo iz seznama <code>L1</code> tako da zbrišemo element <code>X</code>.</p>
<pre>
?- del(1, [1,2,3], L).
  L = [2,3].
?- del(2, [1,2,3,2,5], L).
  L = [1,3,2,5] ;
  L = [1,2,3,5].
?- del(X, [1,2,3], L).
  X = 1, L = [2,3] ;
  X = 2, L = [1,3] ;
  X = 3, L = [1,2].
</pre>'''

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>V bistvu je ta naloga precej podobna nalogi <code>memb/2</code>, le da tokrat iskani element tudi zbrišemo.
Kje se lahko skriva iskani element <code>X</code>, da ga zbrišemo? Spomni se, da ima seznam dva dela, glavo in rep.
Torej sta možnosti dve!</p>
''', '''\
<p>Kaj je najenostavnejša smiselna možnost? Morda brisanje prvega elementa?</p>
''', '''\
<p>Kako brišem nekje iz repa? Seznam razbijem na glavo in rep, rekurzivno (problem je za en element manjši!)
brišem iz repa in ob vračanju iz rekurzije ne pozabim na prej "odtrgano" glavo.</p>
''', '''\
<p>Rekurzivni korak: če predpostavim, da je <code>NewTail</code> rep z že izbrisanim elementom <code>X</code>,
potem je <code>[H|NewTail]</code> celoten seznam z izbrisanim elementom <code>X</code>.</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>del/3</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>
''',

    'eq_instead_of_equ_markup': '''\
<p>Morda bi bil bolj primeren operator za unifikacijo (=)?</p>
''',

    'base_case': '''\
<p><img src="[%@resource base_case.svg%]" /></p>
<p>Si pomislil na robni pogoj? Kaj je najbolj enostaven primer, kateri element v seznamu najlažje zbrišeš?</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>
''',

    'del_from_empty_list_success': '''\
<p>Iz praznega seznama ne moreš uspešno zbrisati nobenega elementa!</p>
<p>Če brišem iz praznega seznama, ne dobim praznega seznama ali tudi karkoli drugega kot rezultat, ampak naj prolog
preprosto ne uspe -- tega niti ne potrebuješ pisati kot pravilo, ker je to prologov privzet odgovor:
saj veš, da z največjim veseljem reče "no"! :)</p>
<p>Če je to tvoj robni pogoj, ga še enkrat premisli: na katerem mestu je najlažje zbrisati element v seznamu?</p>
''',

    'lost_heads': '''\
<p><img src="[%@resource lost_heads.svg%]" /></p>
<p>Element je zbrisan, ampak prav tako so tudi vsi elementi pred njim, kajne?
Si pozabil dati glavo nazaj na začetek seznama, ko se vračaš iz rekurzije?</p>
<p>Poskusi postaviti naslednje vprašanje prologu:</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>Si morda pozabil (copy/paste?) in uporabil <code>[X|T]</code> namesto bolj splošnega
<code>[H|T]</code> v rekurzivnem primeru?</p>
<p>Od spodnjih dveh vprašanj prologu prvo deluje, drugo pa ne.</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>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
kot rezultat seznam <code>BigList</code>. ;)</p>
''',
}