name = 'len/2' slug = 'Izračunaj dolžino danega seznama' description = '''\
len(L, Len)
: Len
je dolžina seznama L
.
?- len([1,2,3], Len). Len = 3.''' plan = ['''\
Prazen seznam ni prav pretirano dolg, če pa ni prazen, pa ima glavo in rep.
''', '''\Če je rep (seznam brez ene glave) dolg LenT
, potem je celoten seznam dolg LenT + 1
.
Če vzamem stran eno glavo, rekurzija mi reši (za ena) manjši problem in če rezultatu rekurzije prištejem 1, potem sem dobil ravno dolžino celotnega 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? Kateri seznam je najkrajši od vseh seznamov na svetu?
''', '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': '''\Kako dolg je prazen seznam? 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 vrednost elementa (glave) namesto njegove dolžine (ena)? ;)
''', '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 + 1)
? S tem vsiljuješ rekurziji
da mora
Si morda zapisal pogoj oblike N is N + 1
? Predpostavi, da je N
recimo enak 3. S tem
si v resnici rekel, da mora 3 biti enako kot 4 (3+1). Prolog je logičen jezik in zato z največjim veseljem
reče ne! Uporabi novo spremenljivko, za odvečne bo tako ali tako poskrbel "garbage collector".