name = 'rev/2' slug = 'Obrni seznam' description = '''\
rev(L1, L2)
: seznam L2
ima elemente v obratnem vrstnem redu kot seznam L1
.
?- rev([1,2,3], X). X = [3,2,1]. ?- rev([], X). X = [].''' plan = ['''\
To je ena najlepših in najbolj poučnih nalog. Klasična rekurzija! Problem poskusi zmanjšati. Seveda, prevedi na krajši seznam.
''', '''\Seznamu odvzamem glavo, rekurzija mi obrne rep in vse, kar moram na koncu narediti jaz je, da glavo vstavim nazaj v obrnjen rep na pravo mesto.
''', '''\Če je podani seznam L
sestavljen iz glave H
in repa T
in če predpostavim, da rekurzija obrne T
v obrnjen rep RT
in če RT
na konec
dodam H
, potem je rezultat obrnjen seznam L
.
Operator ==
je strožji od operatorja =
v smislu, da je za slednjega dovolj,
da elementa lahko naredi enaka (unifikacija). Morda z uporabo =
narediš predikat
rev/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 trivialno obrniti?
''', '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?
''', 'base_case_at_len1': '''\Ta robni pogoj je seveda povsem smiseln, a ga vseeno popravi tako, da bo deloval tudi za prazen seznam. Vendar ne imej dveh robnih pogojev, ker bo to podvajalo rešitve./p> ''', 'arbitrary_base_case': '''\
Kaj je rezultat obračanja praznega seznama? Gotovo ne karkoli (spremenljivka brez določene vrednosti)!
''', '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 rev(T, [RevTail|H])
? S tem vsiljuješ rekurziji
da mora H
vstavi izven rekurzivnega klica.
Od predikatov last/2
, shiftleft/2
ali shiftright/2
tukaj ne bo veliko
pomoči. Poskusi raje brez, bo lažje.
Vstavljaš morda glavo nazaj na začetek obrnjenega repa? To ni pravo mesto, ker s tem samo sestaviš nazaj enak seznam kot na začetku.
''', 'invalid_insert_at_end': '''\Spomni se, rep seznama je vedno seznam! Kako vstaviš element na zadnje mesto?
''', 'conc_arg_not_list': '''\Vsi trije argumenti predikata conc/3
morajo biti seznami. Si prepričan,
da si ga tako uporabil?