name = 'last_elem/2' slug = 'Vrni zadnji element seznama' description = '''\
last_elem(L, E)
: E
je zadnji element seznama L
.
?- last_elem([1,2,3], X). X = 3. ?- last_elem([3,2,X], 1). X = 1.''' plan = ['''\
Do prvega elementa v seznamu je enostavno priti, do zadnjega se je treba rekurzivno prebiti.
''', '''\Seznam lahko razbijem na glavo in rep in iščem dalje v repu. Problem sem zmanjšal (rep je manjši od celega seznama), torej lahko uporabim rekurzijo.
''', '''\Če je X
zadnji element repa T
, potem je X
tudi zadnji element
celega seznama, ki je oblike [H|T]
.
Operator ==
je strožji od operatorja =
v smislu, da je za slednjega dovolj,
da elementa lahko naredi enaka (unifikacija).
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? Kaj je najbolj enostaven primer? Kaj, če ima seznam samo en element?
''', '[]_should_not_succeed': '''\Kako si lahko uspešno našel zadnji element v praznem seznamu? Verjetno potrebuješ drugačen robni pogoj.
''', 'list_returned': '''\Vračaš seznam namesto elementa.
''', 'clumsy_conc_use': '''\Uporabljaš conc/3
? Zanimiva ideja. Ne pozabi, da mora drugi seznam, ki ga konkateniraš
biti dolžine ena, če hočeš doseči to kar želiš. Torej vzorec oblike [X]
, kajne?
Uporabljaš conc/3
? Zanimiva ideja, da se rešiti tudi tako. Vendar boš moral še malo premisliti.
Ne pozabi, conc/3
ima tri argumente, vsi so seznami. Premisli, kakšen vzorec potrebuješ...
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?
''', 'final_hint': '''\Zanimivost: se spomniš kako smo rekli, da lahko predikat conc/3
uporabljamo za iskanje vzorcev?
Tudi zadnji element seznama je na nek način vzorec. Kaj se zgodi, če konkateniram poljuben seznam _
in seznam dolžine ena (v tem vrstnem redu)? Seznam dolžine ena seveda zapišemo kot [Element]
.
Poskusi prolog vprašati tole:
?- conc(_, [Element], [a,b,c,d,e,f,q]).
Znaš sedaj dobiti zadnji element s pomočjo conc/3
? To bo že še prišlo prav. Seveda pa je dostop
do zadnjega elementa še vedno potraten, O(n). Zato, če ni važno od kje ali kam dostopati, se splača vedno delati
s prvim elementom.
Kaj pa naredi tole? ;)
?- conc([a,b,c], [q], L).