180 likes | 283 Views
Logikprogrammering ons 11/9 David Hjelm. Repetition.
E N D
Repetition • Listor är sammansatta termer. De består av en ordnad mängd element. Elementen i en lista kan vara vilka termer som helst. Listor läses från vänster till höger, det ”vänstraste” elementet är alltså det första och det ”högraste” är det sista i listan. • [första,andra,tredje,fjärde] En lista med atomer • [Två,Variabler] En lista med variabler • [1,blandad,Lista] En lista med olika typerav termer • [] Den tomma listan(utan element) • [[en,lista],[av],[listor]] En lista av listor
Repetition • Antingen är en lista den tomma listan eller så består den av huvud och svans. Huvudet på en lista är det första elementet i listan. Svansen är en lista med resten av elementen. Det sista elementet i en lista har alltid tomma listan som svans. • Listan [a,b,c] består av huvudet a och svansen [b,c] som består av huvudet b och svansen [c] som har huvudet c och svansen [] . • Den tomma listan har varken huvud eller svans.
Repetition • En lista kan delas upp i huvud och svans så här: [Huvud|Svans] • Generellt kan en (icke-tom) lista skrivas som [A,B,…,K|Resten] där A,B,…,K är de första elementen i listan och Resten är resten av listan. [a,b,c] är samma som [a|[b,c]] som är samma som [a,b|[c]] som är samma som [a,b,c|[]]
Repetition • Tecken är atomer av längd 1 • Strängar är listor med tecken • Strängar skrivs i SICStus prolog som ”sträng” - vilket bara är ett enklare sätt att skriva listan [s,t,r,ä,n,g] • Motsvarigheten till den tomma listan [] kallas den tomma strängen”” . Den tomma listan och den tomma strängen är precis samma sak. • ”pelle” är samma som [p,e,l,l,e] som är samma som [p,e,l,l,e|[]] som är samma som [p,e,l,l,e|””]
Dagens föreläsning • Predikat med listor • hänga_gubbe/1 • Rekursiva predikat med listor • lika_långa/2 • member/2 • append/3
Predikat med listor – hänga gubbe/1 • hänga_gubbe/1 lyckas för listor med exakt 8 element, där det andra och sjätte elementet är 'n' och 't', och det första och sjunde elementet är lika: hänga_gubbe([A,n,B,C,D,t,A,E]). ?- hänga_gubbe("Lisa och Pelle"). no ?- hänga_gubbe("infantil"). yes
hänga_gubbe/1 forts hänga_gubbe([A,n,B,C,D,t,A,E]). ?- hänga_gubbe([A,A,B,A,A,B|As]). A = n, B = t, As =[n,_1] ?- hänga_gubbe([A,A,A,A|As]). A = n, As = [_1,t,n,_2] ?- hänga_gubbe([A,A,A,A,A,A|As]). no
Rekursiva predikat med listor • Listor kan vara hur långa som helst. Om man ska skriva predikat som gäller för alla listor, behövs oftast rekursion. • Vi vill skriva ett predikat som kollar om två listor är lika långa. Man skulle kunna skriva det så här, som en stor mängd fakta: lika_långa([],[]). lika_långa([_,_],[_,_]). lika_långa([_,_,_],[_,_,_]). ... • Kommer ändå aldrig att täcka in alla listor, eftersom listor kan vara hur långa som helst.
lika_långa/2 • Vi använder rekursion istället. I rekursiva predikat har man alltid (minst) ett basfall där rekursionen stannar och ett rekursivt fall som innehåller det rekursiva anropet. • Basfall: Tomma listan och tomma listan är lika långa. • Rekursivt fall: Två listor är lika långa om deras svansar är lika långa lika_långa([],[]). lika_långa([_|Xs],[_|Ys]):- lika_långa(Xs,Ys).
lika_långa/2 forts • Vårt predikat: lika_långa([],[]). lika_långa([_|Xs],[_|Ys]):- lika_långa(Xs,Ys). ?- lika_långa(”sverige",”danmark"). yes ?- lika_langa("sverige","norge"). no
lika_långa/2 forts • Ungefär så här fungerar det när prolog kommer fram till svaret för ?lika_långa(”sverige”,”danmark”) : • [s,v,e,r,i,g,e] och [d,a,n,m,a,r,k] är lika långa om [v,e,r,i,g,e] och [a,n,m,a,r,k] är lika långa. • [v,e,r,i,g,e] och [a,n,m,a,r,k] är lika långa om [e,r,i,g,e] och [n,m,a,r,k] är lika långa • [e,r,i,g,e] och [n,m,a,r,k] är lika långa om [r,i,g,e] och [m,a,r,k] är lika långa • [r,i,g,e] och [m,a,r,k] är lika långa om [i,g,e] och [a,r,k] är lika långa • [i,g,e] och [a,r,k] är lika långa om [g,e] och [r,k] är lika långa • [g,e] och [r,k] är lika långa om [e] och [k] är lika långa • [e] och [k] är lika långa om [] och [] är lika långa • [] och [] är lika långa, eftersom tomma listan och tomma listan är lika långa.
lika_långa/2 forts • Och så här fungerar det när prolog kommer fram till svaret för ?lika_långa(”sverige”,”norge”) : • [s,v,e,r,i,g,e] och [n,o,r,g,e] är lika långa om [v,e,r,i,g,e] och [o,r,g,e] är lika långa. • [v,e,r,i,g,e] och [o,r,g,e] är lika långa om [e,r,i,g,e] och [r,g,e] är lika långa • [e,r,i,g,e] och [r,g,e] är lika långa om [r,i,g,e] och [g,e] är lika långa • [r,i,g,e] och [g,e] är lika långa om [i,g,e] och [e] är lika långa • [i,g,e] och [e] är lika långa om [g,e] och [] är lika långa • [g,e] och [] är inte lika långa eftersom det inte finns någon klausul som matchar • Eftersom [g,e] och [] inte var lika långa så misslyckas anropet.
member/2 • member/2 kollar om en term är ett element i en lista • Basfall: Elementet är huvud på listan • Rekursivt fall: Elementet finns i svansen member(X,[X|_]). member(X,[_|Xs]) :- member(X,Xs). ?- member(e,"pelle"). yes ?- member(e,"lisa"). no
member/2 forts • member/2 kan användas för att räkna upp alla element i en lista. ?- member(X,"pelle"). X = p ? ; X = e ? ; X = l ? ; X = l ? ; X = e ? ; no
append/3 • append/3, som kallas conc i kursboken, sätter ihop två listor till en tredje lista. • Basfall: den första listan är tom – resultatet blir den andra listan • Rekursivt fall: den första listan har huvud och svans. I så fall vet vi att den första listans och resultatlistans första element är samma. Resten av resultatlistan fås genom att sätta ihop den första listans svans med den andra listan. append([],Xs,Xs). append([X|Xs],Ys,[X|Zs]) :- append(Xs,Ys,Zs).
append/3 forts append([],Xs,Xs). append([X|Xs],Ys,[X|Zs]) :- append(Xs,Ys,Zs). ?- append([1,2],[3],X). X = [1,2,3] ? ?- append("ja","ja",A),append(A,"men",B),append(B,"san",C). A = [j,a,j,a], B = [j,a,j,a,m,e,n], C = [j,a,j,a,m,e,n,s,a,n] ? yes
append/3 överkurs • Man kan även använda append/3 till att dela upp en lista: ?- append(Xs,Ys,"lisa"). Xs = [], Ys = [l,i,s,a] ? ; Xs = [l], Ys = [i,s,a] ? ; Xs = [l,i], Ys = [s,a] ? ; Xs = [l,i,s], Ys = [a] ? ; Xs = [l,i,s,a], Ys = [] ? ; no