Rekurzivni izpis seznamov
Naloga
Napiši funkcijo dump(xs, n)
, ki kot argument dobi seznam xs
, ki vsebuje števila in sezname, ki vsebujejo števila in sezname, ki vsebujejo števila in sezname, ki ... Kot rezultat naj funkcija vrne niz, ki predstavlja vsebino seznama. Da se izognemo predolgim izpisom, dobi funkcija še en argument, n
: pri vsakem seznamu izpiše le prvih n
elementov; če je poleg teh še kakšen, doda tri pike.
Nekaj primerov
Nasvet 1: Najprej napiši funkcijo, ki pravilo naredi, kar kaže prvi gornji primer in nato funkcijo, ki pravilno naredi, kar kaže drugi primer. Šele nato se loti gnezdenja - rekurzije. S pikami (omejitvijo dolžine) se lahko ukvarjaš, ko si končal vse drugo, saj jih je lahko dodati k že narejeni funkciji.
Nasvet 2: Funkcija naj pripravi seznam nizov, ki jih je potrebno izpisati, v niz ločen z vejicami pa jih postavi s pomočjo metode join
, ki smo si jo ogledali, ko smo se pogovarjali o metodah nizov.
Nasvet 3: Naloge se ne loti v zadnjem trenutku.
Rešitev
Lepa rekurzivna rešitev zloži v seznam vse, kar je treba, v obliki nizov, potem pa kar v return
u to z join
om združi z vejicami in spredaj in zadaj prilepi oklepaje. Seznam pa sestavi takole: v začetku je seveda prazen. Nato vzame prvih n elementov seznama (xs [:n]
) in za vsakega stori tole: če gre za seznam, pokliče dump
, ki vrne seznam v obliki niza. Sicer pa s str
pretvori število v niz. Ko je zanke konec, preverimo, ali ima seznam morda več kot n elementov in v tem primeru dodamo še niz s tremi pikami.
Kdor ne ve za join
, je obsojen na mučenje z vejicami in nalogo reši takole
Zmerno zoprno, a znosno. To vedno in povsod čaka tiste, ki ne vedo za join
.
Rešitev brez rekurzije
Obstajajo problemi, ki niso narejeni za rekurzijo. Vse, kar smo počeli na predavanjih (razen Fibonaccija), so pravzaprav natanko takšni primeri; z rekurzijo smo jih reševali, ker so preprosti.
Obstajajo pa tudi "pravi rekurzivni" problemi. Tale je eden njih. Če hočeš problem, za katerega bi bilo naravno uporabiti rekurzijo, reševati brez uporabe rekurzije, moraš navadno zato res obvladati rekurzijo. Razlog je v tem, da moraš nekako napisati rekurziven program, ne da bi uporabil rekurzijo. Rekurzijo moraš na nek način nagoljufati, odsimulirati. Za to pa je potrebno več in ne manj znanja.
Spodnji program deluje tako, da ima na seznamu toDump
stvari, ki jih mora še zapisati, lepo po vrsti. Kadar ima pred sabo element, ga pač zapiše. Kadar prebere, da mora "dump
ati" seznam, pa to naredi tako, da na seznam stvari, ki jih je potrebno dumpati, doda oklepaj, prvih n elementov tega seznama, pike, če je treba, in zaklepaj.
Naj razume, kdor hoče. Te rešitve ne kažem zato, da bi jo razumeli, temveč zato, da bi videli, zakaj je rekurzija (ki ste jo ta vikend najbrž pošteno preklinjali) boljša kot alternativa.