Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Listen und Akkumulatoren Weitere Beispiele zur Listenmanipulation Akkumulatoren zur Effizienzsteigerung Nicht-deterministischer Automat Quicksort mit Prolog.

Ähnliche Präsentationen


Präsentation zum Thema: "Listen und Akkumulatoren Weitere Beispiele zur Listenmanipulation Akkumulatoren zur Effizienzsteigerung Nicht-deterministischer Automat Quicksort mit Prolog."—  Präsentation transkript:

1 Listen und Akkumulatoren Weitere Beispiele zur Listenmanipulation Akkumulatoren zur Effizienzsteigerung Nicht-deterministischer Automat Quicksort mit Prolog Weitere Beispiele zur Listenmanipulation Akkumulatoren zur Effizienzsteigerung Nicht-deterministischer Automat Quicksort mit Prolog

2 Ein Element an eine Liste anhängen, ein Element löschen add(X,L[X|L]). Das neue Element ist einfach der neue Kopf. del(X,L,L1) (1) ist X der Kopf, einfacher Fall del(X,[X|Tail],Tail) (2) ist X in Tail wird es dort gelöscht del(X,[Y|Tail],[Y|TailL1]):- del(X,Tail, TailL1). del ergibt fail, wenn das zu löschende Element nicht in der Liste ist über backtracking können alle anderen Elemente X aus der Liste gelöscht werden (immer nur eins, nicht alle). del kann auch dazu benutzt werden ein Element an einer beliebigen Stelle in die Liste einzufügen. ?- del(a,L,[1,2,3]) durch backtracking wird 'a' nach hinten durchgereicht. insert(X,List, BiggerList) :- del(X,BiggerList, List). add(X,L[X|L]). Das neue Element ist einfach der neue Kopf. del(X,L,L1) (1) ist X der Kopf, einfacher Fall del(X,[X|Tail],Tail) (2) ist X in Tail wird es dort gelöscht del(X,[Y|Tail],[Y|TailL1]):- del(X,Tail, TailL1). del ergibt fail, wenn das zu löschende Element nicht in der Liste ist über backtracking können alle anderen Elemente X aus der Liste gelöscht werden (immer nur eins, nicht alle). del kann auch dazu benutzt werden ein Element an einer beliebigen Stelle in die Liste einzufügen. ?- del(a,L,[1,2,3]) durch backtracking wird 'a' nach hinten durchgereicht. insert(X,List, BiggerList) :- del(X,BiggerList, List).

3 Ein Element löschen loesche(X,[X|L],L). loesche(X,[Y|L],[Y|L1]):- loesche(X,L,L1). [trace] ?- loesche(1,[1,2,1,3],L). Call: (7) loesche(1, [1, 2, 1, 3], _G9797) ? creep Exit: (7) loesche(1, [1, 2, 1, 3], [2, 1, 3]) ? creep L = [2, 1, 3] ; Redo: (7) loesche(1, [1, 2, 1, 3], _G9797) ? creep Call: (8) loesche(1, [2, 1, 3], _G9876) ? creep Call: (9) loesche(1, [1, 3], _G9879) ? creep Exit: (9) loesche(1, [1, 3], [3]) ? creep Exit: (8) loesche(1, [2, 1, 3], [2, 3]) ? creep Exit: (7) loesche(1, [1, 2, 1, 3], [1, 2, 3]) ? creep L = [1, 2, 3] ; Durch Backtracking werden konsekutiv die 1en gelöscht loesche(X,[X|L],L). loesche(X,[Y|L],[Y|L1]):- loesche(X,L,L1). [trace] ?- loesche(1,[1,2,1,3],L). Call: (7) loesche(1, [1, 2, 1, 3], _G9797) ? creep Exit: (7) loesche(1, [1, 2, 1, 3], [2, 1, 3]) ? creep L = [2, 1, 3] ; Redo: (7) loesche(1, [1, 2, 1, 3], _G9797) ? creep Call: (8) loesche(1, [2, 1, 3], _G9876) ? creep Call: (9) loesche(1, [1, 3], _G9879) ? creep Exit: (9) loesche(1, [1, 3], [3]) ? creep Exit: (8) loesche(1, [2, 1, 3], [2, 3]) ? creep Exit: (7) loesche(1, [1, 2, 1, 3], [1, 2, 3]) ? creep L = [1, 2, 3] ; Durch Backtracking werden konsekutiv die 1en gelöscht

4 Sublist S ist eine Subliste von L wenn (1) L in zwei Listen L1 und L2 zerlegt werden kann (2) L2 in S und eine Liste L3 zerlegt werden kann. sublist(S,L):- append(L1,L2,L), append(S,L3,L2). ?- sublist([c,d,e],[a,b,c,d,e,f]) ?- sublist([c,e][a,b,c,d,e,f]) generiere "alle" Sublisten: ?- sublist(S,[a,b,c]). ausprobieren: übergeneriert z.B. [ ] zweimal, warum? S ist eine Subliste von L wenn (1) L in zwei Listen L1 und L2 zerlegt werden kann (2) L2 in S und eine Liste L3 zerlegt werden kann. sublist(S,L):- append(L1,L2,L), append(S,L3,L2). ?- sublist([c,d,e],[a,b,c,d,e,f]) ?- sublist([c,e][a,b,c,d,e,f]) generiere "alle" Sublisten: ?- sublist(S,[a,b,c]). ausprobieren: übergeneriert z.B. [ ] zweimal, warum?

5 Permutationen Zweistelliges Prädikat, ein Argument ist die Ausgangsliste, das andere die permutierte Variante. (1) wenn die erste Liste leer ist, muss die zweite auch leer sein (2) wenn die erste Liste nicht leer ist, so hat sie die Form [X|L] und eine Permutation kann wie folgt erstellt werden: erstelle erst eine permutation L1 von L (rekursiver Aufruf) und füge dann X an jeder Stelle von L1 ein um jeweils eine andere Permutation zu erhalten. Zweistelliges Prädikat, ein Argument ist die Ausgangsliste, das andere die permutierte Variante. (1) wenn die erste Liste leer ist, muss die zweite auch leer sein (2) wenn die erste Liste nicht leer ist, so hat sie die Form [X|L] und eine Permutation kann wie folgt erstellt werden: erstelle erst eine permutation L1 von L (rekursiver Aufruf) und füge dann X an jeder Stelle von L1 ein um jeweils eine andere Permutation zu erhalten. L L1 X permutiere L zu L1 füge X in L1 ein

6 Permutationen pemutation([ ],[ ]). pemutation([X|L],P):- permutation(L,L1), insert(X,L1,P). oder alternativ: lösche ein Element X von der ersten Liste, permutiere den Rest zu P und füge X am Beginn von P ein. pemutation2([ ],[ ]). pemutation2(L,[X|P]):- del(X,L,L1), permutation2(L1,P). ?- permutation([red,blue,green],P). P=[red,blue,green] P=[red,green,blue] P=[blue,red,green]... pemutation([ ],[ ]). pemutation([X|L],P):- permutation(L,L1), insert(X,L1,P). oder alternativ: lösche ein Element X von der ersten Liste, permutiere den Rest zu P und füge X am Beginn von P ein. pemutation2([ ],[ ]). pemutation2(L,[X|P]):- del(X,L,L1), permutation2(L1,P). ?- permutation([red,blue,green],P). P=[red,blue,green] P=[red,green,blue] P=[blue,red,green]...

7 Akkumulatoren Die bisherigen Beispiele zur rekursiven Programmierung konnten keine Zwischenergebnisse mitführen. Der Wert eines rekursiven Aufrufs war unabhängig vom Kontext. Beispiel umkehren einer Liste = Reihenfolge der Elemente umdrehen. [1,2,3,4] → [4,3,2,1] Mit append: reverse([ ],[ ]). reverse([X|L],R) :- reverse(L,RL), append(RL,[X ],R). %X rutscht von vorne nach hinten Die bisherigen Beispiele zur rekursiven Programmierung konnten keine Zwischenergebnisse mitführen. Der Wert eines rekursiven Aufrufs war unabhängig vom Kontext. Beispiel umkehren einer Liste = Reihenfolge der Elemente umdrehen. [1,2,3,4] → [4,3,2,1] Mit append: reverse([ ],[ ]). reverse([X|L],R) :- reverse(L,RL), append(RL,[X ],R). %X rutscht von vorne nach hinten

8 Akkumulatoren [1,2,3,4] → [4,3,2,1] Mit append: reverse([ ],[ ]). reverse([X|L],R) :- reverse(L,RL), append(RL,[X ],R). Wie lange wird reverse rekursiv aufgerufen? Bis die Eingangsliste beim letzten Element angekommen ist: L ist leer und X ist 4! Dann matcht reverse([ ],[ ]). Es ergibt sich RL ist [ ]. append wird zum ersten mal aufgerufen: [ ] wird an X angehängt. [1,2,3,4] → [4,3,2,1] Mit append: reverse([ ],[ ]). reverse([X|L],R) :- reverse(L,RL), append(RL,[X ],R). Wie lange wird reverse rekursiv aufgerufen? Bis die Eingangsliste beim letzten Element angekommen ist: L ist leer und X ist 4! Dann matcht reverse([ ],[ ]). Es ergibt sich RL ist [ ]. append wird zum ersten mal aufgerufen: [ ] wird an X angehängt.

9 Akkumulatoren [1,2,3,4] → [4,3,2,1] Mit append: reverse([ ],[ ]). reverse([X|L],R) :- reverse(L,RL), append(RL,[X ],R). die Ausgabeliste des ersten append Aufrufs ist [x]. Vorletzer rekursiver Aufruf(Aufstieg). reverse([3|4],R) reverse(L=[4], RL = [4]) und damit wird append mit append([4],[3],R) aufgerufen und R wird: [4,3]. und so weiter und sofort. Aufgabe: machen Sie sich den ganzen Aufstieg klar, bis die Liste umgedreht ist. [1,2,3,4] → [4,3,2,1] Mit append: reverse([ ],[ ]). reverse([X|L],R) :- reverse(L,RL), append(RL,[X ],R). die Ausgabeliste des ersten append Aufrufs ist [x]. Vorletzer rekursiver Aufruf(Aufstieg). reverse([3|4],R) reverse(L=[4], RL = [4]) und damit wird append mit append([4],[3],R) aufgerufen und R wird: [4,3]. und so weiter und sofort. Aufgabe: machen Sie sich den ganzen Aufstieg klar, bis die Liste umgedreht ist.

10 Akkumulatoren [1,2,3,4] → [4,3,2,1] Mit append: reverse([ ],[ ]). reverse([X|L],R) :- reverse(L,RL), append(RL,[X ],R). was ist der Nachteil dieser Vorgehensweise: append ist linear wird aber für jedes Element der Liste wieder aufgerufen: insgesamt wird der Aufwand für reverse quadratisch (Details im Leiss-Skript Seite 20/21). Implementation mit Akkumulator: ● Staple die Elemente der Eingabeliste auf eine Liste von ● Zwischenergebnissen(=Akkumulator) ● Beginne mit dem leeren Stapel ● Gib den Stapel aus, wenn die Eingabeliste leer ist [1,2,3,4] → [4,3,2,1] Mit append: reverse([ ],[ ]). reverse([X|L],R) :- reverse(L,RL), append(RL,[X ],R). was ist der Nachteil dieser Vorgehensweise: append ist linear wird aber für jedes Element der Liste wieder aufgerufen: insgesamt wird der Aufwand für reverse quadratisch (Details im Leiss-Skript Seite 20/21). Implementation mit Akkumulator: ● Staple die Elemente der Eingabeliste auf eine Liste von ● Zwischenergebnissen(=Akkumulator) ● Beginne mit dem leeren Stapel ● Gib den Stapel aus, wenn die Eingabeliste leer ist

11 Reverse mit Akkumulator reverse(L,R) :- reverse_acc(L,[ ],R). reverse_acc([X|L],Acc,R):- reverse_acc(L,[X|Acc],R). reverse_acc([],Acc,Acc). Die Eingabeliste [1,2,3,4] wird der Reihe nach geköpft und auf den Akkumulator geschrieben. Wenn die Liste leer ist wird der Akkumulator auf die Ausgabeliste geschoben und diese nach oben durchgereicht bis schliesslich das zweistellige Aufrufprädikat reverse erreicht wird. Der Algorithmus ist linear in der Größe der Eingabe. Aufgabe: machen Sie sich klar warum reverse(L,R) :- reverse_acc(L,[ ],R). reverse_acc([X|L],Acc,R):- reverse_acc(L,[X|Acc],R). reverse_acc([],Acc,Acc). Die Eingabeliste [1,2,3,4] wird der Reihe nach geköpft und auf den Akkumulator geschrieben. Wenn die Liste leer ist wird der Akkumulator auf die Ausgabeliste geschoben und diese nach oben durchgereicht bis schliesslich das zweistellige Aufrufprädikat reverse erreicht wird. Der Algorithmus ist linear in der Größe der Eingabe. Aufgabe: machen Sie sich klar warum

12 Anzahl der Elemente einer Liste Lösung ohne Akkumulator: len([ ],0). len([H|T],N) :- len(T,N1), N is N1 +1. Aufgabe: denken Sie darüber nach, wie das Programm für die Liste [1,2,3,4] abläuft. Das rekursive Prädikat köpft die Liste und ruft mit der Restliste rekursiv auf. Die Rekursion stoppt, wenn T = [ ] und somit N1 = 0. Damit wird N für den letzten rekursiven Aufruf 1. Bedeutet das, dass schon die leere Liste Länge 1 hat? Lösung ohne Akkumulator: len([ ],0). len([H|T],N) :- len(T,N1), N is N1 +1. Aufgabe: denken Sie darüber nach, wie das Programm für die Liste [1,2,3,4] abläuft. Das rekursive Prädikat köpft die Liste und ruft mit der Restliste rekursiv auf. Die Rekursion stoppt, wenn T = [ ] und somit N1 = 0. Damit wird N für den letzten rekursiven Aufruf 1. Bedeutet das, dass schon die leere Liste Länge 1 hat?

13 Anzahl der Elemente einer Liste Lösung mit Akkumulator: len2(L,N,) :- lenacc(L,0,N). lenacc([],Acc,Acc). lenacc([H|T],Acc,N) :- Acc1 is Acc +1, lenacc(T,Acc1,N). Klarmachen: der neue Aufruf hat jeweils um 1 erhöhtem Akkumulator und um 1 verkürzte Liste. In prozeduralen Programmiersprachen arbeitet man mit Iteration und einer Variablen, die Skopus über die gesamte Iteration hat. In Prolog wird eine Hilfsvariable mit einem Startwert mitgeführt die jeweils an den nächsten rekursiven Aufruf übergeben wird. Bei Ende der Rekursion steht das Ergebnis unmittelbar in der Hilfsvariablen. Lösung mit Akkumulator: len2(L,N,) :- lenacc(L,0,N). lenacc([],Acc,Acc). lenacc([H|T],Acc,N) :- Acc1 is Acc +1, lenacc(T,Acc1,N). Klarmachen: der neue Aufruf hat jeweils um 1 erhöhtem Akkumulator und um 1 verkürzte Liste. In prozeduralen Programmiersprachen arbeitet man mit Iteration und einer Variablen, die Skopus über die gesamte Iteration hat. In Prolog wird eine Hilfsvariable mit einem Startwert mitgeführt die jeweils an den nächsten rekursiven Aufruf übergeben wird. Bei Ende der Rekursion steht das Ergebnis unmittelbar in der Hilfsvariablen.

14 Nicht-deterministischer Automat vgl. Bratko S.94ff Eine abstrakte Maschine, die Input einliest, etwa einen String von Symbolen und die ● Entscheidet einen String abzulehnen oder zu akzeptieren ● Eine Reihe von Zuständen hat und immer in einem Zustand ist ● Von einem Zustand in den andern gehen kann ● Deren interne Struktur als Transitionsgraph repräsentiert werden kann Eine abstrakte Maschine, die Input einliest, etwa einen String von Symbolen und die ● Entscheidet einen String abzulehnen oder zu akzeptieren ● Eine Reihe von Zuständen hat und immer in einem Zustand ist ● Von einem Zustand in den andern gehen kann ● Deren interne Struktur als Transitionsgraph repräsentiert werden kann

15 Nicht-deterministischer Automat vgl. Bratko S.94ff S3S3 S2S2 S4S4 a b a b null S1

16 Nicht-deterministischer Automat vgl. Bratko S.94ff Der Automat akzeptiert einen String wenn: (1) er startet in irgendeinem Initialzustand (2) er endet in einem Finalzustand (3) die Übergangslabels auf dem Pfad korrespondieren mit dem gesamten Inputstring Automatenrepräsentation in Prolog: (a) unäre Relation final(S3) (b) 3-stellige Übergangsrelation trans(S1,X,S2) (c) binäre Übergangsrelation silent(S1,S2) Der Automat akzeptiert einen String wenn: (1) er startet in irgendeinem Initialzustand (2) er endet in einem Finalzustand (3) die Übergangslabels auf dem Pfad korrespondieren mit dem gesamten Inputstring Automatenrepräsentation in Prolog: (a) unäre Relation final(S3) (b) 3-stellige Übergangsrelation trans(S1,X,S2) (c) binäre Übergangsrelation silent(S1,S2)

17 Nicht-deterministischer Automat vgl. Bratko S.94ff Beispiel aus dem Übergangsgraphen final(s3). trans(s1,a,s1). trans(s1,a,s2). trans(s1,b,s1). trans(s2,b,s3). trans(s3,b,s4). silent(s2,s4). silent(s3,s1). Inputstrings werden als Prologlisten etwa [a,a,b] übergeben Beispiel aus dem Übergangsgraphen final(s3). trans(s1,a,s1). trans(s1,a,s2). trans(s1,b,s1). trans(s2,b,s3). trans(s3,b,s4). silent(s2,s4). silent(s3,s1). Inputstrings werden als Prologlisten etwa [a,a,b] übergeben

18 Nicht-deterministischer Automat vgl. Bratko S.94ff accept Prädikat für Zustand State (1) leerer String wird akzeptiert, wenn für den Zustand State des Automaten final zutrifft (2) ein nicht-leerer String wird akzeptiert, wenn nach dem Lesen des ersten Symbols ein Zustand State1 erreicht wird, von dem aus der Reststring akzeptiert wird (3) ein nicht-leerer String wird akzeptiert, wenn durch einen silent move (Spontanübergang) ein State1 erreicht wird, von dem aus der String akzeptiert wird accept Prädikat für Zustand State (1) leerer String wird akzeptiert, wenn für den Zustand State des Automaten final zutrifft (2) ein nicht-leerer String wird akzeptiert, wenn nach dem Lesen des ersten Symbols ein Zustand State1 erreicht wird, von dem aus der Reststring akzeptiert wird (3) ein nicht-leerer String wird akzeptiert, wenn durch einen silent move (Spontanübergang) ein State1 erreicht wird, von dem aus der String akzeptiert wird

19 Nicht-deterministischer Automat vgl. Bratko S.94ff accept(State,[ ]) :- final(State). accept(State[X|Reststring]) :- trans(State,X,State1), accept(State1,Reststring). accept(State,String) :- silent(State,State1), accept(State1,String). accept(State,[ ]) :- final(State). accept(State[X|Reststring]) :- trans(State,X,State1), accept(State1,Reststring). accept(State,String) :- silent(State,State1), accept(State1,String). X first rest null string

20 Nicht-deterministischer Automat vgl. Bratko S. 94ff Anwendungen Entscheide eine Eingabe ?- accept(S1,[a,a,a,b]) yes. Gib alle akzeptierten Strings der Länge 3 von s1 als Startzustand aus – Teilsprache des Automaten. ?- accept(s1,[X1,X2,X3]). X1=a X2=a X3 =b; X1=b X2=a X3 =b; no. ?- String=[_,_,_], accept(s1,String). Ausgabe? Anwendungen Entscheide eine Eingabe ?- accept(S1,[a,a,a,b]) yes. Gib alle akzeptierten Strings der Länge 3 von s1 als Startzustand aus – Teilsprache des Automaten. ?- accept(s1,[X1,X2,X3]). X1=a X2=a X3 =b; X1=b X2=a X3 =b; no. ?- String=[_,_,_], accept(s1,String). Ausgabe?

21 Quicksort Klassischer sehr effizienter Sortieralgorithmus nach dem Prinzip „teile und herrsche“. (vgl. Skript Hans Leiss, S. 22) Sortiere eine Liste L von Zahlen nach ihrer Größe zu L' (i) Wähle ein Element aus X (ii) Zerlege L in eine Liste Bigger, in der alle Elemente Y>= X und eine Liste Smaller, in der alle Elemente Y < X (iii) Sortiere die Listen Bigger und Smaller nach dem gleichen Prinzip (Rekursion) (iv) Bilde L' durch append(Bigger', [X|Smaller'],L') Klassischer sehr effizienter Sortieralgorithmus nach dem Prinzip „teile und herrsche“. (vgl. Skript Hans Leiss, S. 22) Sortiere eine Liste L von Zahlen nach ihrer Größe zu L' (i) Wähle ein Element aus X (ii) Zerlege L in eine Liste Bigger, in der alle Elemente Y>= X und eine Liste Smaller, in der alle Elemente Y < X (iii) Sortiere die Listen Bigger und Smaller nach dem gleichen Prinzip (Rekursion) (iv) Bilde L' durch append(Bigger', [X|Smaller'],L')

22 Quicksort quicksort([ ],[ ]). quicksort([ X|Xs],Ys):- partition(X,Xs,Big,Small), quicksort(Big,Bs), quicksort(Small,Ss), append(Bs,[X|Ss],Ys). quicksort([ ],[ ]). quicksort([ X|Xs],Ys):- partition(X,Xs,Big,Small), quicksort(Big,Bs), quicksort(Small,Ss), append(Bs,[X|Ss],Ys).

23 Quicksort partition(_,[ ],[ ],[ ]). partition(X,[Z|Zs], ZsBig, [Z|ZsSmall]) :- Z=X, partition(X,Zs, ZsBig, ZsSmall). Beispielaufruf: quicksort wird mit [2,4,3,1] gestartet: 1. Aufruf partition(2,[4,3,1],Big,Small). Da 4 >= 2 matcht 3. partition Regel 2. (rekursiver) Aufruf: partition(2,[3,1],ZsBig,ZsSmall) Liste Big wird zusammengebaut wenn Rekursion zurückkehrt und Tail ZsBig belegt. Da 3>= 2 matcht wieder die 3. Regel 3. (rekursiver) Aufruf: partition(2,[1],ZsBig,ZsSmall) Da 1 < 2 matcht 2. Regel. 4. (rekursver) Aufruf: partition(2,[],ZB,ZS). Da Verarbeitungsliste leer ist matcht die 1. Regel. Zusammenbau erfolgt und Big wird mit [4,3] Small mit [1] an Quicksort zurückgegeben. partition(_,[ ],[ ],[ ]). partition(X,[Z|Zs], ZsBig, [Z|ZsSmall]) :- Z=X, partition(X,Zs, ZsBig, ZsSmall). Beispielaufruf: quicksort wird mit [2,4,3,1] gestartet: 1. Aufruf partition(2,[4,3,1],Big,Small). Da 4 >= 2 matcht 3. partition Regel 2. (rekursiver) Aufruf: partition(2,[3,1],ZsBig,ZsSmall) Liste Big wird zusammengebaut wenn Rekursion zurückkehrt und Tail ZsBig belegt. Da 3>= 2 matcht wieder die 3. Regel 3. (rekursiver) Aufruf: partition(2,[1],ZsBig,ZsSmall) Da 1 < 2 matcht 2. Regel. 4. (rekursver) Aufruf: partition(2,[],ZB,ZS). Da Verarbeitungsliste leer ist matcht die 1. Regel. Zusammenbau erfolgt und Big wird mit [4,3] Small mit [1] an Quicksort zurückgegeben.

24 Quicksort mit Akkumulator Spare append Aufrufe: akkumuliere alle schon gesehenen Eingabeelemente auf dem Akkumulator quicksort(Xs,Ys):- quicksort_acc(Xs,[ ],Ys). quicksort_acc([ X|Xs],Acc,Ys):- partition(X,Xs,Big,Small), quicksort_acc(Big,Acc,Zs), quicksort_acc(Small,[X|Zs],Ys). %Implementierung partition bleibt gleich Spare append Aufrufe: akkumuliere alle schon gesehenen Eingabeelemente auf dem Akkumulator quicksort(Xs,Ys):- quicksort_acc(Xs,[ ],Ys). quicksort_acc([ X|Xs],Acc,Ys):- partition(X,Xs,Big,Small), quicksort_acc(Big,Acc,Zs), quicksort_acc(Small,[X|Zs],Ys). %Implementierung partition bleibt gleich

25 Hausaufgabe (1) In den Skripten Hadersbeck und Leiss den Stand der Vorlesung verifizieren (Tipp: Hadersbeckskript, S.35) (2) In Bratko Kapitel 4 lesen, versuchen Sie alle 4 dargestellten Probleme und deren Lösung in Prolog zu verstehen. (3) Implementieren Sie die Programme für den Automaten und Quicksort und probieren Sie sie aus. (1) In den Skripten Hadersbeck und Leiss den Stand der Vorlesung verifizieren (Tipp: Hadersbeckskript, S.35) (2) In Bratko Kapitel 4 lesen, versuchen Sie alle 4 dargestellten Probleme und deren Lösung in Prolog zu verstehen. (3) Implementieren Sie die Programme für den Automaten und Quicksort und probieren Sie sie aus.


Herunterladen ppt "Listen und Akkumulatoren Weitere Beispiele zur Listenmanipulation Akkumulatoren zur Effizienzsteigerung Nicht-deterministischer Automat Quicksort mit Prolog."

Ähnliche Präsentationen


Google-Anzeigen