# coding=utf-8 name = 'conc/3' slug = 'Združi dva seznama (konkatenacija)' description = '''\

conc(?L1, ?L2, ?L): seznam L dobiš tako, da seznamu L1 na konec dodaš elemente seznama L2.

?- conc([1,2], [3,4], X).
  X = [1,2,3,4].
?- conc(X, [], [1,2,3]).
  X = [1,2,3].
''' plan = ['''\

Začnimo z enostavnim vprašanjem: kaj bi bil rezultat, če konkateniram prazen seznam in seznam L2?

''', '''\

Sedaj recimo, da ima prvi seznam točno en element. Začasno ga vzemimo stran, ostali smo s praznim prvim seznamom. Kaj ni ta situacija podobna oni od prej? Seveda, problem smo zmanjšali za en element in ga tako prevedli na manjši problem! Uporabimo rekurzijo za rešitev tega manjšega problema. A na koncu ne pozabimo rezultat rekurzije ustrezno dopolniti s prej odvzetim prvim elementom...

''', '''\

Deklarativno/logično razmišljanje: Recimo, da ima prvi seznam L1 glavo H in rep T. Če je (rekurzivni) rezultat konkatenacije T in L2 nek seznam L3 in če seznamu L3 na začetek dodam element H, kaj s tem dobim? Konkatenacijo seznamov L1 in L2!

'''] 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 conc/3 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? Kaj je najbolj enostaven primer? Kaj bi bil, recimo, rezultat, če je prvi seznam kar prazen?

''', '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).

''', 'timeout': '''\

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? Morda npr. v rekurziji zmanjšuješ prvi seznam, ustaviš pa se pri praznem drugem seznamu (ali obratno)?

''', 'final_hint': '''\

Predikat conc/3 bomo večinoma uporabljali za vse drugo kot samo za konkatenacijo dveh seznamov. Med drugim je uporaben "v obratni smeri" za delitev seznama na dva dela, poskusi naslednja vprašanja:

?- conc(L1, L2, [a,b,c,d]).

?- conc([X,Y], L2, [a,b,c,d,e,f]).

Si opazil, da je drugo vprašanje v bistvu vrnilo prva dva elementa iz seznama [a,b,c,d,e,f]?

Nadalje je conc/3 uporaben za iskanje vzorcev v seznamu, npr. takole:

?- conc(_, [X,X|_], [a,b,c,c,d,e,f,f,g,h,h]).

Tako je, to vprašanje najde vse možnosti, kjer se dva elementa ponovita drug za drugim v seznamu (vzorec X,X). V bistvu smo rekli "nekaj poljubnih elementov (lahko tudi nič) je spredaj, potem sta dva enaka, potem pa spet nekaj poljubnih elementov (lahko nič) zadaj." Še veliko drugih koristi bo od conc/3, jih boš že še sproti spoznal.

''', }