name = 'sum/2' slug = 'Izračunaj vsoto elementov v seznamu' description = '''\
sum(L, Sum)
: Sum
je vsota vseh elementov v seznamu L
.
?- sum([1,2,3], Sum). Sum = 6.''' plan = ['''\
Vsota elementov praznega seznama ni prav velika. Sicer pa seštevamo, element po element, lepo rekurzivno.
''', '''\Če je vsota elementov v repu (seznamu brez glave H
) enaka SumT
, potem je vsota elementov
celotnega seznama enaka SumT + H
.
Če vzamem stran eno glavo, rekurzija mi reši (za ena) manjši problem in če rezultatu rekurzije prištejem vrednost prej odvzete glave, potem sem dobil ravno vsoto elementov celega seznama.
'''] hint = { 'eq_instead_of_equ': '''\Operator ==
je strožji od operatorja =
v smislu, da je za slednjega dovolj,
da elementa lahko naredi enaka (unifikacija). Morda z uporabo =
narediš predikat
memb/2
delujoč tudi v kakšni drugi smeri.
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? Koliko je vsota elementov v praznem seznamu?
''', '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 N
enako kot N + 1
ali kaj podobno logično 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?
''', 'arbitrary_base_case': '''\Koliko je vsota elementov praznega seznama? Podaj konkretno številko!
''', 'args_not_instantiated': '''\Napaka, ki si jo dobil od prologa, pomeni, da ob uporabi aritmetike niso podane vse vrednosti spremenljivk. Pri aritmetiki je vrstni red ciljev (konjunktov) žal pomemben.
Morda poskusiš pomakniti aritmetiko bolj na konec?
''', '=_instead_of_is': '''\Si morda uporabil =
namesto is
? Operator =
je namenjen prilagajanju
(unifikaciji) in poskusi pustiti obe strani čimbolj nespremenjeni, medtem ko operator is
izvede
dejanski aritmetični izračun izraza na svoji desni strani ter ga šele potem poskusi prilagoditi (!)
svoji levi strani.
Kaj si res prištel ena namesto vrednosti elementa (glave)? Kopiranje od prejšnje naloge, morda? ;)
''', 'forcing_result_onto_recursion': '''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.
Je tvoj rekurzivni klic oblike len(T, LenT + H)
? S tem vsiljuješ rekurziji
da mora
Si morda zapisal pogoj oblike N is N + H
? Predpostavi, da je N
recimo enak 3.
S tem si v resnici rekel, da mora 3 biti enako kot 3+H. Prolog je logičen jezik in zato z največjim veseljem
reče ne (seveda če H ni enako nič, he he)! Uporabi novo spremenljivko, za odvečne bo tako ali tako
poskrbel "garbage collector".