name = 'insert/3' slug = 'Vstavi element na poljubno mesto v seznamu' description = '''\
insert(X, L1, L2)
: seznam L2
dobimo iz L1
tako, da vstavimo element X
na poljubno mesto. Predikat naj vrne vse možne rešitve, eno za drugo.
?- insert(1, [2,3], L). L = [1,2,3] ; L = [2,1,3] ; L = [2,3,1].''' plan = ['''
Kam v seznam lahko vstavimo element X
? Spomni se, da ima seznam dva dela, glavo in rep.
Torej sta možnosti dve! Tako je, na tem mestu dve, v repu pa spet lahko vstavimo ali v njegovo glavo ali v rep od repa.
In tako dalje, rekurzija na pomoč!
Kaj je najenostavnejša možnost? Vstavimo na začetek!
''', '''\Kako vstavim nekam v rep? Seznam razbijem na glavo in rep, rekurzivno (problem je za en element manjši!) vstavim v rep in ob vračanju iz rekurzije ne pozabim na prej "odtrgano" glavo.
''', '''\Rekurzivni korak: če predpostavim, da je NewTail
rep z že vstavljenim elementom X
,
potem je [H|NewTail]
celoten seznam z vstavljenim elementom X
.
Operator ==
je strožji od operatorja =
v smislu, da je za slednjega dovolj,
da elementa lahko naredi enaka (unifikacija). Morda z uporabo =
narediš predikat
insert/3
delujoč tudi v kakšni drugi smeri. To bo kasneje znalo priti prav!
Seveda pa lahko nalogo rešiš brez obeh omenjenih operatorjev, spomni se, da lahko unifikacijo narediš implicitno že kar v argumentih predikata (glavi stavka).
''', 'eq_instead_of_equ_markup': '''\Morda bi bil bolj primeren operator za unifikacijo (=)?
''', 'base_case': '''\Si pomislil na robni pogoj? Na katero mesto v seznamu najlažje vstaviš nek element?
''', 'recursive_case': '''\Robni primer deluje. Kaj pa rekurzivni, splošni, primer?
''', 'predicate_always_false': '''\Vse kaže, da tvoj predikat vedno vrne "false". Si mu dal pravilno ime, si se morda pri imenu zatipkal?
Č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?
Možno je seveda tudi, da so tvoji pogoji prestrogi ali celo nemogoči (kot bi bila npr. zahteva,
da je X
hkrati starš in sestra od Y
ali kaj podobno zlobnega).
Je morda na delu potencialno neskončna rekurzija? Kako se bo ustavila?
Morda pa je kriv tudi manjkajoč, neustrezen ali preprosto nekompatibilen (s splošnim primerom) robni pogoj?
''', 'ins_results_in_empty_list': '''\Kako je lahko rezultat vstavljanja v seznam prazen seznam?
Če je to tvoj robni pogoj, ga še enkrat premisli: kaj je rezultat vstavljanja?
''', 'ins_results_in_arbitrary_result': '''\Kako je lahko rezultat vstavljanja v seznam poljuben seznam oz. karkoli?
Če je to tvoj robni pogoj, ga še enkrat premisli: kaj je rezultat vstavljanja?
''', 'lost_heads': '''\Element je vstavljen, ampak vsi pred njim so se pa izgubili, kajne? Si pozabil dati glavo nazaj na začetek seznama, ko se vračaš iz rekurzije?
Poskusi postaviti naslednje vprašanje prologu in preglej vse rešitve:
?- insert(q, [a,b,c,d], L).
Si morda pozabil (copy/paste?) in uporabil [X|T]
namesto bolj splošnega
[H|T]
v rekurzivnem primeru?
Od spodnjih dveh vprašanj prologu prvo deluje, drugo pa ne.
?- insert(d, [d,d,d,d,e,f,g], L).
?- insert(d, [a,b,c,d,e,f,g], L).