Informatik/Jahrgangsstufe Q/001 Klausuren/Themensortiert/10
Transcription
Informatik/Jahrgangsstufe Q/001 Klausuren/Themensortiert/10
Aufgabe 2: PROLOG a) Erläutern Sie kurz, was man in PROLOG unter den Begriffen Faktum, Prädikat, Konstante, Variable und Regel versteht. Geben Sie jeweils ein kleines Beispiel. b) Die „Beziehungskiste“ zwischen Karl, Otto, Susi und Moni kann wie folgt beschrieben werden: Karl liebt Moni. Otto hasst Susi. Susi liebt Karl. Otto liebt alle Mädchen, welche auch von Karl geliebt werden. Susi hasst alle Jungen, die von Moni geliebt werden. Moni liebt alle Jungen, die Susi hassen. Karl wird von den Mädchen gehasst, die von Otto geliebt werden. Karl hasst gar kein Mädchen. Schreiben Sie ein PROLOG-Programm, welches die oben genannten Fakten kennt und in diesem Wirrwarr herausfindet, wer ein ideales_paar(X,Y), wer ein hassendes_paar(X,Y) und wer ein ungleiches_paar(X,Y) ist. Hinweis: Ein ideales_paar sei dabei ein Paar, in dem sich beide Partner lieben, ein hassendes_paar sei ein Paar, in dem sich beide Partner hassen und ein ungleiches_paar sein ein Paar, in dem der eine Partner den anderen liebt, wogegen dieser den ersten Partner hasst. c) Nehmen wir an, es gäbe keine einseitige Liebe, d. h. jeder, der von einem Partner geliebt wird, liebt auch diesen. Eine Umsetzung dieser Eigenschaft wäre z. B. durch die Regel liebt(X,Y) :- liebt(Y,X). gegeben. Erläutern Sie die Problematik dieser Regel, wenn nach allen „idealen Paaren“ aus Teilaufgabe b) gefragt wird. Aufgabe 2: Prolog − logische Programmiersprachen a) Erläutern Sie kurz, was man in PROLOG unter den Begriffen Faktum, Prädikat, Konstante, Variable und Regel versteht. Geben Sie jeweils ein kleines Beispiel. b) Die rechts abgebildete „Karte“soll mit vier Farben eingefärbt werden. Schreiben Sie ein Prolog-Programm, welches eine Lösung für die Farben rot, gelb, grün und blau ausgibt. A C B E c) An einem runden Tisch sitzen symmetrisch verteilt sechs Personen (siehe rechte Abbildung). i) Erstellen Sie für diesen Sachverhalt eine PROLOG-Wissensbasis. (Zum Beispiel mit Hilfe eines Prädikates links_neben(X,Y), mit X sitzt links neben Y.) ii) Formulieren Sie eine Regel nachbar(A,B), wobei A und B Tischnachbarn sind. iii) Eine Regel gegenueber soll die am Tisch einander direkt gegenübersitzenden Personen finden, z. B. Theo und Paul. Formulieren Sie diese Regel. iv) Schreiben Sie ein rekursives Prädikat sitzt_mit_am_tisch(X,Y), mit dessen Hilfe man herausfindet, ob eine Person mit am Tisch sitzt. sitzt_mit_am_tisch(olli,Y) sollte z. B. nacheinander alle Namen des Tisches ausgeben. D Aufgabe 1: Du kennst vielleicht diese russischen Holzpüppchen, in denen immer noch eine kleinere drin steckt. Rechts ist eine schematische Abbildung von solchen ineinandersteckenden russischen Puppen: katarina olga natasha a) Stelle die drei direkten Lagebeziehungen in Form von Fakten in Prolog dar: direktin(... , ...). b) Definiere ein Prädikat in/2 (d. h. ein Prädikat mit zwei Parametern), dass uns sagt welche Puppe (direkt oder indirekt) in welcher anderen Puppe steckt. Die Anfrage in(katarina,natasha) z.B. sollte wahr sein, während in(olga,katarina) fehlschlagen sollte. Hinweis: Nutze dabei auch das Prädikat aus Teilaufg. a). c) Welche Ausgabe erhältst du bei der Anfrage in(X,katarina)? d) Welche Ausgabe erhältst du bei der Anfrage in(X,Y), wenn alle Lösungen angefordert werden? e) Stelle das Backtracking beim Aufruf in(katarina,irina) grafisch dar. Lösung: Aufgabe 1: a) Eine Möglichkeit ist die folgende: direktin(katarina,olga). direktin(olga,natasha). direktin(natasha,irina). b) in(X,Y):- direktin(X,Y). in(X,Y):- direktin(Z,Y), in(X,Z). c) Ausgabe ‚no’ d) Ausgabe: X = katarina Y = olga ; X = olga Y = natasha ; X = natasha Y = irina ; X = katarina Y = natasha ; X = olga Y = irina ; X = katarina Y = irina e) in(katarina, irina) direktin(katarina, irina) schlägt fehl direktin(natascha, irina), ist erfüllt direktin(katarina, natasha) schlägt fehl in(katarina,natasha) direktin(olga, natasha), ist erfüllt in(katarina,olga) direktin(katarina, olga) ist erfüllt irina Aufgabe 2: Folgende Reisemöglichkeiten stehen zur Auswahl: byCar(auckland,hamilton). /* byCar(hamilton,raglan). byCar(valmont,saarbruecken). byCar(valmont,metz). ← /* /* /* Dies bedeutet: Man kommt mit dem Auto von Auckland nach Hamilton. Die anderen Prädikate sind ebenfalls so zu lesen. byTrain(metz,frankfurt). byTrain(saarbruecken,frankfurt). byTrain(metz,paris). byTrain(saarbruecken,paris). */ */ */ */ byPlane(frankfurt,bangkok). byPlane(frankfurt,singapore). byPlane(paris,losAngeles). byPlane(bangkok,auckland). byPlane(losAngeles,auckland). a) Schreibe ein Prädikat travel/2, welches herausfindet, ob es möglich ist, von einer Stadt zu einer anderen Stadt zu reisen. Die Wahl des Verkehrsmittels soll dabei keine Rolle spielen. Beispiel: Dein Programm sollte die Anfrage travel(valmont,raglan) mit ‘yes’ beantworten. b) Plant man seine Reise etwas genauer, so ist es interessant zu wissen, über welche Stadt man zum Ziel gelangt. Schreibe deshalb ein Prädikat travel/3, welches dir ausgibt, über welche Zwischenpunkte du von der einen Stadt zur anderen gekommen bist. Beispiel: Dein Programm sollte bei der Anfrage travel(valmont,paris,go(valmont,metz,go(metz,paris))) die Antwort ‘yes’ ausgeben. Fragt man dein Programm nach travel(valmont,losAngeles,X) so sollte es X = go(valmont,metz,go(metz,paris,go(paris,losAngeles))) ausgeben. c) Zur noch besseren Routenplanung ist auch eine Ausgabe des Verkehrsmittels zweckmäßig. Erweitere dein Prädikat travel/3, so dass es dir nicht nur mitteilt, über welche Zwischenpunkte die Reise geht, sondern auch sagt, mit welchem Verkehrsmittel die einzelnen Teilstücke zurückgelegt wurden. Beispiel: die Anfrage travel(valmont,losAngeles,X) sollte X = car(valmont, metz, train(metz, paris, plane(paris, losAngeles))) ausgeben. Lösungen: Aufgabe 2: a) Eine Möglichkeit ist: traveldirekt(X,Y):- byCar(X,Y); byTrain(X,Y); byPlane(X,Y). travel(X,Y):- traveldirekt(X,Y). travel(X,Y):- traveldirekt(X,Z),travel(Z,Y). b) Die Erweiterung könnte wie folgt aussehen: traveldirekt(X,Y):- byCar(X,Y); byTrain(X,Y); byPlane(X,Y). travel(X,Y,go(X,Y)):- traveldirekt(X,Y). travel(X,Y,go(X,Z,F)):- traveldirekt(X,Z),travel(Z,Y,F). c) Mit Fahrzeugangabe: travel(X,Y,car(X,Y)):- byCar(X,Y). travel(X,Y,train(X,Y)):- byTrain(X,Y). travel(X,Y,plane(X,Y)):- byPlane(X,Y). travel(X,Y,car(X,Z,F)):- byCar(X,Z),travel(Z,Y,F). travel(X,Y,train(X,Z,F)):- byTrain(X,Z),travel(Z,Y,F). travel(X,Y,plane(X,Z,F)):- byPlane(X,Z),travel(Z,Y,F). Aufgabe 3: Im Zusammenhang mit Listen haben wir im Unterricht bereits einige Prädikate kennen gelernt. Hier sollen nun neue Prädikate entwickelt und analysiert werden: a) Betrachte das folgende Prädikat wti/4: wti(_, _, [], []). wti(X, Y, [X | Rest], [Y | Rest]). wti(Z1, Z2, [X | Rest], [X | NeuerRest]):Z1 \= X, wti(Z1, Z2, Rest, NeuerRest). I) Welche Ausgabe wird bei der Anfrage wti(3,9,[1,2,3,4,5],X) produziert? II) Notiere die Ausgabe zur Anfrage wti(1,2,[0,1,1,0,0,0,1,0],Y). III) Beschreibe allgemein die Wirkung des Prädikats wti/4. b) Erweitere das oben angegebene Prädikat, so dass die unter a.III) beschriebene Aktion auf die ganze Liste ausgeweitet wird. c) Schreibe ein Prädikat restliste/3, welches von einer Liste die Restliste nach dem ersten Auftreten eines Elements zurück gibt. Beispiel: restliste([1,2,3,4,5],3,X) wird mit X = [4,5] beantwortet. d) Gegeben ist das folgende Programm: wti( [], Liste, Liste ). wti([Head|Tail], SListe, X ) :split( Head, Tail, Kleiner, Groesser), wti(Groesser, Rest, X ), wti(Kleiner, SListe, [Head|Rest]). /* split(X,Liste,Kleine,Grosse) teilt die Liste */ /* bezüglich des Vergleichselements X in die zwei */ /* Listen Kleine und Grosse. */ Im ersten Aufruf sollte das dritte Argument immer eine leere Liste sein. Beispiel: wti([4,3,8,7,1,5,4,8],Ergebnis,[]). I) Welche Ausgabe wird bei obigem Beispiel getätigt? II) Gib dem Prädikat einen aus Informatikersicht sinnvollen Namen. III) Beschreibe die Unterschiede zu dem aus dem Unterricht bekannten ähnlichen Verfahren. e) In der folgenden Routine split/4 aus obigen Programm haben sich Fehler eingeschlichen. Kommentiere jeden Fehler, indem du angibst, inwiefern sich dieser Fehler äußert (Compilerfehler, Laufzeitfehler). Korrigiere jeden Fehler einzeln oder gib das gesamte Teilprogramm in korrekter Form an. split(_, [], K, G). split(Element, [Head|Tail], Kleiner, Groesser):Head <= Element, split(Element, Tail, hilfKleiner, Groesser), append(Head, hilfKleiner, Kleiner). split(Element, [Head|Tail], Kleiner, Groesser):= Head > Element, split(Element, Tail, Kleiner, Groesser), append(Head, Groesser, Groesser). Lösungen: Aufgabe 3: a) I) X = [1,2,9,4,5] II) X = [0,2,1,0,0,0,1,0] III) Das erste vorkommende Element der Liste, welches mit dem ersten Argument des Prädikats wti übereinstimmt, wird durch das zweite Argument ersetzt. Die so gewonnene Liste wird im 4. Argument zurückgegeben. b) wti(_, _, [], []). wti(X, Y, [X | Rest], [Y | NeuerRest]):wti(X,Y,Rest,NeuerRest). wti(Z1, Z2, [X | Rest], [X | NeuerRest]):Z1 \= X, wti(Z1, Z2, Rest, NeuerRest). c) restliste([X | Rest], X, Rest). restliste([_ | End], X, Rest):restliste(End, X, Rest). d) I) Ergebnis = [1,3,4,4,5,7,8,8] II) Ein sinnvoller Name wäre Quicksort. III) Der wesentliche Unterschied ist der, dass das Prädikat keinen appendBefehl benötigt. Dies gelingt, indem immer eine Liste „mitgeschleppt“ wird, in der sofort die Vereinigung der beiden Teillisten gespeichert wird. Deshalb muss allerdings auch am Anfang eine leere Liste mitgegeben werden, da diese am Schluss wieder hinten angefügt wird. e) Die richtige Prozedur müsste wie folgt aussehen: split(_, [], [], []). split(Element, [Head|Tail], Kleiner, Groesser):Head =< Element, split(Element, Tail, Kleiner1, Groesser), append([Head],Kleiner1,Kleiner). split(Element, [Head|Tail], Kleiner, Groesser):Head > Element, split(Element, Tail, Kleiner, Groesser1), append([Head],Groesser1,Groesser). Die Fehler im einzelnen: 1. Zeile: bei einer leeren Liste sollte sowohl die Kleiner- als auch die Groesser-Liste leer sein. In der falschen Version sind K und G undefiniert. (Laufzeitfehler). 3. Zeile: <= ist falsch. Richtig: =< (Compilerfehler) 4. Zeile: hilfKleiner muss HilfKleiner heißen, da eine Variable benötigt wird. (Compilerfehler) 5. Zeile: append benötigt 3 Listen. Head ist aber nur ein Element. Besser: [Head]. (Compilerfehler). 6. Zeile: := ist falsch. Richtig :- (Compilerfehler). 9. Zeile: Groesser ist sowohl Input- als auch Outputvariable. (Laufzeitfehler). Aufgabe 4: Aus dem Unterricht kennst du die Baumstruktur. Ein Baum konnte 6 entweder leer (nil) oder eine Wurzel mit zwei Teilbäumen (baum(W,L,R)) sein. 3 9 a) Stelle den rechts abgebildeten Baum mit Hilfe des Prädikats baum/3 dar. 4 7 10 b) Zeichne den zum folgenden Ausdruck zugehörigen Baum: baum(2, baum(1, nil, nil), baum(7, baum(3, nil, 8 baum(6, nil, nil)), baum(8, nil, nil))) c) Implementiere ein Prädikat knotenanzahl/2, welches als Input einen Baum und als Output die Anzahl der Knoten des Baumes enthält. Beispiel: knotenanzahl(baum(3,baum(2,nil,nil),baum(5,baum(4,nil,nil),nil)),X) würde X = 4 ausgeben. d) Implementiere ein Prädikat baumhoehe/2, welches die Anzahl der Ebenen − also die Baumhöhe − eines Baumes ausgibt. Hinweis: Der Baum aus Teilaufgabe a) hat übrigens die Höhe 4! Lösungen: Aufgabe 4: a) baum(6,baum(3,nil,baum(4,nil,nil)), baum(9,baum(7,nil,baum(8,nil,nil)), baum(10,nil,nil))) b) Wie rechts abgebildet. c) 2 1 knotenanzahl(nil,0). knotenanzahl(baum(W,L,R),Anz):knotenanzahl(L,AnzL), knotenanzahl(R,AnzR), Anz is 1+AnzL+AnzR. d) baumhoehe(nil,0). baumhoehe(baum(W,L,R),H):baumhoehe(L,H1), baumhoehe(R,H2), H1>H2, H is H1+1. baumhoehe(baum(W,L,R),H):baumhoehe(L,H1), baumhoehe(R,H2), H1=<H2, H is H2+1. 7 3 8 6 Aufgabe 1: Prolog – Listen a) Wir nennen eine Liste gedoppelt, wenn sie aus zwei aufeinanderfolgenden Blöcken besteht, die genau gleich sind. Z. B. ist gedoppelt([a,b,c,a,b,c]) wahr, da sie aus [a,b,c] gefolgt von [a,b,c] besteht. gedoppelt([go,willy,go]) ist andrerseits falsch. Schreiben Sie ein Prädikat gedoppelt(Liste), welches wahr wird, wenn Liste eine gedoppelte Liste ist. b) Ein Palindrom ist ein Wort, das vorwärts- und rückwärtsgelesen genau gleich ist. ´rentner´, ´otto´, und ´lagerregal´ sind z.B. Palindrome. Schreiben Sie − ohne das Systemprädikat append zu verwenden − ein Prädikat palindrom(List), das testet, ob eine Liste ein Palindrom ist. Auf die Anfrage ?- palindrom([r,e,n,t,n,e,r]). sollte Prolog z. B. ´yes´ antworten. Auf die Anfrage ?- palindrom([d,i,e,s,n,i,c,h,t]). sollte Prolog ´no´ antworten. c) Schreiben Sie zwei Prädikate zur Listenmultiplikation: (I) Das Prädikat liste_mal_faktor/3 soll bewirken, dass jedes Element einer Liste mit einem Faktor multipliziert wird. Zur Anfrage ?- liste_mal_faktor(5, [1,2,3,4], Liste) antwortet Prolog: Liste = [5,10,15,20]. Zur Anfrage ?- liste_mal_faktor(2, [3,6,9], [6,9,12]) antwortet Prolog: ´no´. (II) Das Prädikat liste_mal_liste/3 soll nun jedes Element der ersten Liste mit jedem Element der zweiten Liste multiplizieren und alle Produkte der Reihe nach in der dritten Liste ausgeben. Zur Anfrage ?- liste_mal_liste([2,5], [1,2,3,4], Liste) antwortet Prolog: Liste = [2,4,6,8,5,10,15,20]. Zur Anfrage ?- liste_mal_liste([1,3], [3,6], [3,6,9,12]) antwortet Prolog: ´no´. ([3,6,9,18] wäre richtig gewesen) Zur Anfrage ?- liste_mal_liste([], [3,6,9,12], Liste) antwortet Prolog: Liste = []. d) Gegeben ist das folgende Prolog-Programm: tut_was([],[]). tut_was([X|Xs],Ys):- tut_was(Xs,Zs), macht_was(X,Zs,Ys). macht_was(X,[],[X]). macht_was (X,[Y|Ys],[X,Y|Ys]):- X =< Y. macht_was (X,[Y|Ys],[Y|Zs]):- X > Y, macht_was (X,Ys,Zs). (I) Veranschaulichen Sie die Funktionsweise des Programms am Aufruf: ?- tut_was([69, 95, 2, 58, 64],Liste). (II) Beschreiben Sie die Bedeutung der einzelnen Prädikate tut_was und macht_was, indem Sie zu jeder Programmzeile eine sinnvolle Kommentarzeile formulieren. Lösung: Aufgabe 1: a) gedoppelt(L) :- append(X,X,L). b) %% palindrom ohne reverse und append palindrom(W) :- palindrom2(W,[]). palindrom2(L,L). palindrom2([_|L],L). palindrom2([H|T],L2) :- palindrom2(T,[H|L2]). %% palindrom mit reverse und append palindrom1(W) :- reverse(W,W). reverse([], []). reverse([Head | Tail], Reverse):reverse(Tail, RestReverse), append(RestReverse, [Head], Reverse). c.1) % multi(Faktor,Y,Z) multipliziert jedes Element der ersten Liste Y % mit dem Faktor und fügt das Ergebnis in der Liste Z ein. multi(Faktor,[],[]). multi(Faktor,[H|Tail],[H_neu|Tail_neu]):H_neu is H * Faktor, multi(Faktor,Tail,Tail_neu). c.2) % multi(X,Y,Z) multipliziert jedes Element der ersten Liste % mit jedem Element der zweiten Liste und fügt das Ergebnis in der Liste Z ein. multi2([],L,[]). multi2([H|Tail],L1,Liste):multi(H,L1,First), multi2(Tail,L1,Second), append(First,Second,Liste). d) tut_was([69, 95, 2, 58, 64],Ys) tut_was([95, 2, 58, 64],Zs) tut_was([2, 58, 64],Ys) tut_was([58, 64],Ys) tut_was([64],Ys) tut_was([],[]) macht_was(64,[],[64]) macht_was(58,[64],[58,64]) macht_was(2,[58,64], [2,58,64]) macht_was(95,[2,58,64], [2,58,64,95]) → Zs = [2,58,64,95] macht_was(69,[2,58,64,95],Ys) macht_was(69,[58,64,95],[2|Ys]) macht_was(69,[64,95],[2,58|Ys]) macht_was(69,[95],[2,58,64,69|Ys]) macht_was(69,[],[2,58,64,69,95]) → Ys = [2,58,64,69,95] Prolog – Bäume Aufgabe 2: 10 Aus dem Unterricht kennen Sie die Baumstruktur. Ein Baum konnte entweder leer (nil) oder eine Wurzel mit zwei Teilbäumen (baum(W,L,R)) sein. a) Stellen Sie den rechts abgebildeten Baum mit Hilfe des Prädikats baum/3 dar. b) Zeichnen Sie den zum folgenden Ausdruck zugehörigen Baum: 9 8 6 7 baum(6, baum(3, nil, baum(4, nil, nil)), baum(9, baum(7, nil, baum(8, nil, nil)), baum(10, nil, nil))) c) Implementieren Sie ein Prädikat postorder/2, welches als Input einen Baum erhält und als Ergebnis eine Liste mit den Baumelementen in Postorder-Reihenfolge zurückgibt. Beispiel: 5 8 ?- postorder(baum(5,baum(2,nil,nil),baum(8,nil,nil)),Liste). würde Liste = [2,8,5] ausgeben, ?- postorder(baum(4,baum(2,nil,baum(3,nil,nil)),baum(5,nil,nil)),Liste). würde Liste = [3,2,5,4] ausgeben, d) Implementieren Sie ein Prädikat sortiert/1, welches als Input einen Baum erhält und überprüft, ob der Baum ein Suchbaum ist Beispiel: ?- sortiert(baum(5,baum(2,nil,nil),baum(8,nil,nil))). würde ´yes´ ausgeben, ?- sortiert(baum(5,baum(8,nil,nil),baum(2,nil,nil))). würde ´no´ ausgeben. Hinweis: Ein Suchbaum besitzt folgende Eigenschaften: (1) Alle Elemente des linken Teilbaums sind kleiner als die Wurzel und alle Elemente des rechten Teilbaums sind größer als die Wurzel. (2) Beide Teilbäume eines Suchbaums sind entweder leer oder selbst Suchbäume. Lösung: Aufgabe 2: a) baum(10,baum(9,baum(8,nil,nil),baum(7,nil,baum(8,nil,nil))), baum(6,baum(5,nil,nil),baum(4,nil,nil))) b) 6 3 9 4 7 10 8 c) postorder(nil,[]). postorder(baum(W,L,R),Liste):postorder(L,Liste1), postorder(R,Liste2), append(Liste1,Liste2,Liste3), append(Liste3,[W],Liste). d) sortiert(nil). sortiert(baum(W,nil,nil)). sortiert(baum(W,baum(W1,L1,R1),nil)):- 4 sortiert(baum(W1,L1,R1)), W1 < W. sortiert(baum(W,nil,baum(W2,L2,R2))):sortiert(baum(W2,L2,R2)), W < W2. sortiert(baum(W,baum(W1,L1,R1),baum(W2,L2,R2))):sortiert(baum(W1,L1,R1)), sortiert(baum(W2,L2,R2)), W1 < W, W < W2. Aufgabe 3: Prolog – Rekursion a) Stellen Sie folgende Fakten in Form eines Prolog-Programms dar: Um 7.00 Uhr morgens... o ist Köln von Bonn in 40 Minuten erreichbar. o ist Bonn von Köln in 30 Minuten erreichbar. o ist Düsseldorf von Köln in 35 Minuten erreichbar. o ist Köln von Düsseldorf in 55 Minuten erreichbar. o ist Aachen von Köln in 70 Minuten erreichbar. o ist Köln von Aachen gar nicht erreichbar (Vollsperrung der A4). o ist Bonn von Aachen in 120 Minuten erreichbar. o ist Aachen von Bonn auch nicht erreichbar (Vollsperrung der A61). o ist Köln von Odenthal in 20 Minuten erreichbar. o ist Odenthal von Köln in 10 Minuten erreichbar. b) Schreiben Sie ein Prädikat berechne_zeit(A,B,Zeit), welches zu zwei beliebigen Städten A und B die benötigte Fahrzeit von A nach B in Minuten berechnet. Beispiel: ?- berechne_zeit(odenthal,aachen,Zeit). würde Zeit = 90 ausgeben. c) Schreiben Sie ein neues Prädikat berechne_weg(A,B,Liste), welches die Fahrtroute als Liste ausgibt. Beispiel: ?- berechne_weg(odenthal,aachen,Liste). würde Liste = [odenthal, koeln, aachen] ausgeben. Lösung: Aufgabe 3: a) zeit(bonn,koeln,40). zeit(koeln,bonn,30). zeit(koeln,duesseldorf,35). zeit(duesseldorf,koeln,55). zeit(koeln,aachen,70). zeit(aachen,bonn,120). zeit(odenthal,koeln,20). b) berechne_zeit(A,B,Zeit):zeit(A,B,Zeit). berechne_zeit(A,B,Zeit):zeit(A,C,Zeit1), berechne_zeit(C,B,Zeit2), Zeit is Zeit1 + Zeit2. c) berechne_weg(A,B,[A,B]):zeit(A,B,_). berechne_weg(A,B,[A|Liste]):zeit(A,C,_),berechne_weg(C,B,Liste). Aufgabe 1: Prolog – Listen a) Implementieren Sie ein Prädikat produkt/2, welches zu einer Liste das Produkt über alle Listenelemente berechnet. b) Gegeben ist das folgende Prolog-Programm: wti([],[[]]). wti([X|Rs],[[X|Rs]|Hilf]):wti(Rs,Hilf). (i) Welche Antwort gibt Prolog auf die Frage ?- wti([a,b],L). (ii) Welche Antwort gibt Prolog auf die Frage ?- wti(L,[[1,2],[1],[]]). Begründen Sie. (iii) Veranschaulichen Sie den rekursiven Abstieg für den Aufruf wti([x,y,z],L). c) Schreiben Sie ein Prädikat indexbereich/3, welches zu einer unteren und einer oberen Grenze eine Liste mit allen natürlichen Zahlen dieses Zahlenbereichs ausgibt. Beispiel: Zu indexbereich(3,7,L) gibt Prolog L=[3,4,5,6,7] aus. Zu indexbereich(4,E,[4,5,6]) gibt Prolog E=6 aus. d) In Prolog gibt es das Systemprädikat not(...), welches die Auswertung eines logischen Ausdrucks umdreht. So liefert not(4>9) als Antwort yes. Der Aufruf not(element(3,[1,2,3])) liefert no. Implementieren Sie ein Prädikat liste_zu_menge/2, welches eine Liste in eine Menge überführt. Das heißt, dass Elemente, die in der Liste mehrfach auftreten, in der Menge nur einfach auftauchen. Das oben erwähnte Systemprädikat kann dafür nützlich sein. Beispiel: Der Aufruf liste_zu_menge([2,3,2,1,3],Menge). wird von Prolog mit Menge=[3,1,2] beantwortet. Die Reihenfolge der Elemente in der Menge ist dabei allerdings beliebig. Lösung: Aufgabe 1: a) produkt([],nn). produkt([X],X). produkt([K|Rs],P):produkt(Rs, P1), P is P1*K. b) (i) L=[[a,b],[b],[]] (ii) no. richtig wäre [[1,2],[2],[]] (iii) wti([x,y,z],L) wti([X|Rs],[[X|Rs]|Hilf]) X=x, Rs=[y,z], Hilf= wti([y,z],Hilf) wti([X|Rs],[[X|Rs]|Hilf]) X=y, Rs=[z], Hilf= wti([z],Hilf) wti([X|Rs],[[X|Rs]|Hilf]) X=z, Rs=[], Hilf= wti([],[]) wti([],[]) Hilf=[] Hilf=[[z],[]] Hilf=[[y,z],[z],[]] L=[[x,y,z],[y,z],[z],[]] c) indexbereich(A,A,[A]). indexbereich(A,E,[]):- A > E. indexbereich(A,E,[A|L]):A1 is A+1, indexbereich(A1,E,L). d) element(X,[X|_]). element(X,[Y|Ls]):- element(X,Ls). liste_zu_menge([],[]). liste_zu_menge([A|Ls],Ms):liste_zu_menge(Ls,Ms), element(A,Ls). liste_zu_menge([A|Ls],[A|Ms]):liste_zu_menge(Ls,Ms), not(element(A,Ls)). Aufgabe 2: Prolog – Rekursion a) Die Fibonacci-Funkton fib(n) berechnet sich durch folgende Rekursionsformel: für n > 2 fib(n − 1) + fib(n − 2) fib(n) = 1 für n = 1 oder n = 2 Schreiben Sie ein entsprechendes zweistelliges Prädikat fib/2. b) Ein Geldwechselautomat verfügt über die Münzen im Wert von 1 Cent, 2 Cent, 5 Cent, 10 Cent und 100 Cent. (i) Stellen Sie diesen Sachverhalt in Form von Prolog-Fakten dar. (ii) Zu einem Geldbetrag gibt es unterschiedliche Möglichkeiten der MünzZusammenstellung. Z. B. können 6 Cent in folgender Stückelung zurückgegeben werden: 5 + 1 ; 2 + 2 + 2 ; 2 + 2 + 1 + 1 ; 2 + 1 + 1 + 1 + 1 ; 1 + 1 + 1 + 1 + 1 + 1. Schreiben Sie ein zweistelliges Prädikat, welches zu einem Geldbetrag alle Möglichkeiten der Stückelung berechnet. Ihr Prädikat darf Lösungen auch mehrfach ausgeben, wenn die Reihenfolge der Münzwerte eine andere ist. Lösung: Aufgabe 2: a) fib(0,0). fib(1,1). fib(N,Ergebnis):- N1 is N-1, N2 is N-2, fib(N1,Erg1), fib(N2,Erg2), Ergebnis is Erg1+Erg2. b) muenze(200). muenze(100). muenze(50). muenze(20). muenze(10). muenze(5). muenze(2). muenze(1). stueckelung(0,[]). stueckelung(Betrag,[M|Restliste]):- muenze(M), Betrag >= M, Restbetrag is Betrag - M, stueckelung(Restbetrag,Restliste). Aufgabe 3: Prolog – Rätsel a) Schreiben Sie ein Prolog-Programm, welches das folgende Zahlenrätsel löst. TICK + TRICK + TRACK --------=ATICKI b) Drei Brüder Hans, Franz und Karl programmieren in Prolog, Delphi und Java. Der eine arbeitet unter Win2000, der andere unter OS/2 und der letzte unter Linux. Hans mag kein Java, Karl verteufelt OS/2 und der Delphi-Programmierer arbeitet unter Win2000. Außerdem verabscheut Franz die Programmiersprache Delphi und Java programmieren unter OS/2 ist sowieso eine Katastrophe. (i) Ist die Lösung eindeutig? Geben Sie alle möglichen Kombinationen an. (ii) Implementieren Sie ein Prolog-Programm, welches die erste Fragestellung löst. Lösung: Aufgabe 3: a) ziffer(0). ziffer(1). ziffer(2). ziffer(3). ziffer(4). ziffer(5). ziffer(6). ziffer(7). ziffer(8). ziffer(9). raetsel(T, I, C, K, R, A):ziffer(T), ziffer(I), ziffer(C), ziffer(K), ziffer(R), ziffer(A), T\=I, T\=C, T\=K, T\=R, T\=A, I\=C, I\=K, I\=R, I\=A, C\=K, C\=R, C\=A, K\=R, K\=A, R\=A, I is (3*K) mod 10, U1 is (3*K) // 10, K is (3*C+U1) mod 10, U2 is (3*C+U1) // 10, C is (2*I+A+U2) mod 10, U3 is (2*I+A+U2) // 10, I is (T+2*R+U3) mod 10, U4 is (T+2*R+U3) // 10, T is (2*T+U4) mod 10, A is (2*T+U4) // 10. b) /* Hans - Delphi - Win2k Franz - Prolog - Os/2 Karl - Java – Linux oder Karl - Delphi - Win2k Hans - Prolog - Os/2 Franz - Java – Linux */ junge(hans). junge(franz). junge(karl). loesung(De,Pr,Ja,Wi,Os,Li):- junge(De), junge(Pr), Pr\=De, junge(Ja), Ja\=Pr, Ja\=De, junge(Wi), junge(Os), Os\=Wi, junge(Li), Li\=Os, Li\=Wi, Ja\=hans, Os\= karl, De=Wi, De\=franz, Ja\=Os. Aufgabe 4: Prolog − Datenbanken Gegeben ist die folgende Datenbank: person(1,name(´Hans´,´Hallig´),alter(29),schule(´GS Odenthal´,´Gymnasium Odenthal´)). person(2,name(´Karl´,´Käfer´),alter(31),schule(´GS Voiswinkel´,´Gymnasium Odenthal´)). person(3,name(´Paula´,´Pinki´),alter(30),schule(´GS Odenthal´,´Hauptschule Odenthal´)). person(4,name(´Doris´,´Dries´),alter(29),schule(´GS Voiswinkel´,´Hauptschule Odenthal´)). person(5,name(´Nora´,´Nebel´),alter(31),schule(´GS Blecher´,´Hauptschule Odenthal´)). person(6,name(´Bert´,´Boll´),alter(30),schule(´GS Blecher´,´Gymnasium Odenthal´)). beruf(1,’Maurer’). beruf(2,’Lehrer’). beruf(3,’Diplomarchitektin’). beruf(4,’Zahnärztin’). beruf(5,’Verkäuferin’). beruf(6,’Lehrer’). a) Wie antwortet Prolog auf die folgenden Fragestellungen: (i) person(_,_,A,schule(B,_)). (ii) person(_,A,alter(31),_). (iii) beruf(N,’Lehrer’), person(N,A,_,_). b) Formulieren Sie Anfragen, mit denen man die folgenden Fragestellungen beantworten kann: (i) Wer hat die GS Voiswinkel besucht? (ii) Welchen Beruf hat Doris? (iii) Gibt es eine Zahnärztin, die Hauptschulabschluss hat? (iv) Welche Berufe haben die über 30-jährigen? (v) Wie heißt der Maurer und wie alt ist dieser? Lösung: Aufgabe 4: a) (i) A = alter(29) B = 'GS Odenthal' ; A = alter(31) B = 'GS Voiswinkel' ; A = alter(30) B = 'GS Odenthal' ; A = alter(29) B = 'GS Voiswinkel' ; A = alter(31) B = 'GS Blecher' ; A = alter(30) B = 'GS Blecher' ; no. (ii) A = name('Karl', 'Käfer') ; A = name('Nora', 'Nebel') ; no. (iii) N = 2 A = name('Karl', 'Käfer') ; N = 6 A = name('Bert', 'Boll') ; no. b) (i) person(_,N._,schule(‘GS Voiswinkel’,_)). (ii) person(N,name(‚Doris’,_),_,_), beruf(N,B). (iii) beruf(N,’Zahnärztin’),person(N,_,_,schule(_,’HS Odenthal’)). (iv) person(N,_,alter(A), _), A>30, beruf(N,B). (iv) beruf(N,’Maurer’),person(N,Name,alter(A),_). Aufgabe 3: logische Programmiersprachen − Datenstrukturen in Prolog Folgende Reisemöglichkeiten stehen zur Auswahl: byCar(auckland,hamilton). /* byCar(hamilton,raglan). byCar(valmont,saarbruecken). byCar(valmont,metz). </* /* /* byTrain(metz,frankfurt). byTrain(saarbruecken,frankfurt). byTrain(metz,paris). byTrain(saarbruecken,paris). Dies bedeutet: Man kommt mit dem Auto von Auckland nach Hamilton. Die anderen Prädikate sind ebenfalls so zu lesen. */ */ */ */ byPlane(frankfurt,bangkok). byPlane(frankfurt,singapore). byPlane(paris,losAngeles). byPlane(bangkok,auckland). byPlane(losAngeles,auckland). a) Schreiben Sie ein Prädikat travel/2, welches herausfindet, ob es möglich ist, von einer Stadt zu einer anderen Stadt zu reisen. Die Wahl des Verkehrsmittels soll dabei keine Rolle spielen. Beispiel: Ihr Programm sollte die Anfrage travel(valmont,raglan) mit yes. beantworten. b) Plant man seine Reise etwas genauer, so ist es interessant zu wissen, über welche Stadt man zum Ziel gelangt. Schreiben Sie deshalb ein Prädikat travel/3, welches ausgibt, über welche Zwischenpunkte man von der einen Stadt zur anderen gekommen ist. Beispiel: Ihr Programm sollte bei der Anfrage travel(valmont,paris,[valmont,metz,paris]) die Antwort yes ausgeben. Fragt man Ihr Programm nach travel(valmont,losAngeles,X) so sollte es zuerst X = [valmont, saarbruecken, paris, losAngeles] ausgeben. c) Zur noch besseren Routenplanung ist auch eine Ausgabe des Verkehrsmittels zweckmäßig. Erweiteren Sie das Prädikat travel/3, so dass es nicht nur mitteilt, über welche Zwischenpunkte die Reise geht, sondern auch sagt, mit welchem Verkehrsmittel die einzelnen Teilstücke zurückgelegt wurden. Beispiel: die Anfrage travel(valmont,losAngeles,X) sollte X = [car(valmont, saarbruecken), train(saarbruecken, paris), plane(paris, losAngeles)] ausgeben. Lösung: Aufgabe 3: a) traveldirekt(X,Y):- byCar(X,Y); byTrain(X,Y); byPlane(X,Y). travel(X,Y):- traveldirekt(X,Y). travel(X,Y):- traveldirekt(X,Z),travel(Z,Y). b) travelliste(X,Y,[X,Y]):- traveldirekt(X,Y). travelliste(X,Y,[X|L]):- traveldirekt(X,Z),travelliste(Z,Y,L). c) travelliste(X,Y,[car(X,Y)]):- byCar(X,Y). travelliste(X,Y,[train(X,Y)]):- byTrain(X,Y). travelliste(X,Y,[plane(X,Y)]):- byPlane(X,Y). travelliste(X,Y,[car(X,Z)|F]):- byCar(X,Z),travelliste(Z,Y,F). travelliste(X,Y,[train(X,Z)|F]):byTrain(X,Z),travelliste(Z,Y,F). travelliste(X,Y,[plane(X,Z)|F]):byPlane(X,Z),travelliste(Z,Y,F). Aufgabe 1: Prolog – Listen a) Sie kennen aus der Jahrgangsstufe 12 die Datenstruktur Stapel bzw. Stack. Sie zeichnete sich dadurch aus, dass neue Elemente stets an den Anfang der „Liste“ gesetzt und von dort auch wieder gelöscht wurden. Schreiben Sie in Prolog die Methoden empty/1 ; top/2 ; push/3 und pop/2 Hinweis: Die Fragestellung empty(L1), push(L1,a,L2), push(L2,b,L3), top(L3,X), pop(L3,L4),top(L4,Y). liefert die Antwort: L1 = [] L2 = [a] L3 = [b, a] X = b L4 = [a] Y = a b) Gegeben ist das folgende Prolog-Programm: wti(0,[]). wti(N,[X|Rest]):N1 is N – 1, X is 2 * N, wti(N1,Rest). (i) Welche Antwort gibt Prolog auf die Frage ?- wti(4,Liste). (ii) Welche Antwort gibt Prolog auf die Frage ?- wti(3,[2,4,6]). Begründen Sie. (iii) Welche Antwort gibt Prolog auf die Frage ?- wti(N,[6,4,2]). Begründen Sie. Lösung: Aufgabe 1: a) empty([]). top([X|_],X). push(Liste,X,[X|Liste]). pop([_|Rest],Rest). b) (i) L=[8,6,4,2] (ii) no. richtig wäre [6,4,2] (iii) Variable nicht definiert (N1 is N − 1) Aufgabe 2: Prolog – Rekursion a) Die Werte der Funktion f berechnen sich durch folgende Rekursionsformel: f (n − 1) + 3n(n − 1) + 1 für n > 1 f ( n) = 1 sonst Schreiben Sie ein entsprechendes zweistelliges Prädikat f/2. b) In der Stufe 12 haben Sie in der ersten Klausur eine rekursiv definierte Ziffernfolge kennen gelernt, welche sich wie folgt entwickelt (n = 1, 2, ..., 5). 1, 121, 1213121, 121312141213121, 1213121412131215121312141213121, ... Schreiben Sie ein Prädikat ziffernfolge/2, welches zu einer Zahl n die n-te Ziffernfolge als Liste zurückgibt. c) Das Binärsystem besteht aus den Ziffern 0 und 1. (i) Stellen Sie diesen Sachverhalt in Form von Prolog-Fakten dar. (ii) Für eine Binärzahl mit 4 Stellen gibt es 24 verschiedene Möglichkeiten. Es ist ein Programm zu schreiben, welches alle Möglichkeiten in Form von Listen ausgibt. Die Ausgabe soll mit [0,0,0,0] , [0,0,0,1] , [0,0,1,0] , ... beginnen und mit ....... , [1,1,1,1] aufhören. Lösung: Aufgabe 2: a) f(0,0). fib(1,1). fib(N,Ergebnis):- N1 is N-1, N2 is N-2, fib(N1,Erg1), fib(N2,Erg2), Ergebnis is Erg1+Erg2. b) zf(1,[1]). zf(N,Liste):N1 is N – 1, zf(N1, Liste1), append(Liste1,[N|Liste1],Liste). c) ziffer(0). ziffer(1). bin(0,[]). bin(N,[X|Liste]):N >= 1, ziffer(X), N1 is N - 1, bin(N1, Liste). Aufgabe 3: Prolog – Rätsel Auf einer Speisekarte sind folgende Vor-, Haupt- und Nachspeisen abgedruckt: Hauptgericht Pizza Kartoffelauflauf Pfannekuchen Vorspeise Kartoffelcremesuppe Hühnersuppe Tomatensuppe Nachtisch Pudding Götterspeise Eis Folgende Kombinationen dürfen nicht zusammen bestellt werden: Pfannekuchen mit Hühnersuppe; Kartoffelcremesuppe mit Pizza; Hühnersuppe mit Götterspeise sowie Kartoffelauflauf mit Götterspeise. Stattdessen gibt es die Kartoffelcremesuppe nur mit Eis als Nachtisch zusammen. (i) Welche Suppe und welcher Nachtisch gehört zu jedem Hauptgericht? Ist die Lösung eindeutig? Geben Sie alle möglichen Kombinationen an. (ii) Implementieren Sie ein Prolog-Programm, welches alle Menüs ausgibt. Lösung: Aufgabe 3: /* Pfannekuchen - Kartoffelcremesuppe - Eis Pizza - Tomatensuppe - Götterspeise Kartoffelauflauf – Hühnersuppe – Pudding oder Pfannekuchen – Tomatensuppe - Götterspeise Pizza – Hühnersuppe - Pudding Kartoffelauflauf – Kartoffelcremesuppe – Eis */ hauptgericht(pfannekuchen). hauptgericht(pizza). hauptgericht(kartoffelauflauf). loesung(Ka,To,Hu,Ei,Go,Pu):hauptgericht(Ka), hauptgericht (To), To\=Ka, hauptgericht (Hu), Hu\=To, Hu\=Ka, hauptgericht (Ei), hauptgericht (Go), Go\=Ei, hauptgericht (Pu), Pu\=Go, Pu\=Ei, Hu\=pfannekuchen, Go\= kartoffelauflauf, Ka=Ei, Ka\=pizza, Hu\=Go. Aufgabe 4: Prolog − Datenbanken Gegeben ist die folgende Datenbank: % Datenbank Kundenkartei % kunde(Nummer, name(Vorname, Nachname), stammkunde(JA/NEIN)) kunde(17,kundenname('Karl','König'),stammkunde(ja)). kunde(4,kundenname('Boris','Burgundi'),stammkunde(nein)). kunde(29,kundenname('Franz','Freitag'),stammkunde(nein)). kunde(21,kundenname('Caspar','Castell'),stammkunde(ja)). kunde(42,kundenname('Emil','Endersen'),stammkunde(ja)). % artikel(Nummer, Bezeichnung, Bestand) artikel(1,'Waschmaschine',10). artikel(2,'Trockner',2). artikel(3,'Wäscheständer',37). artikel(4,'Seife',1). artikel(5,'Klammern',1000). artikel(6,'Leine',15). % bestellung(Kundennr, Artikelnr, Stückzahl) bestellung(21,5,2). bestellung(17,3,1). bestellung(17,4,2). bestellung(4,6,20). bestellung(29,1,5). a) Wie antwortet Prolog auf die folgenden Fragestellungen: (i) kunde(_,kundenname(' Karl' ,_),X). (ii) artikel(1,_,Anzahl). (iii) bestellung(_,A,X), artikel(A,' Seife' ,_). b) Formulieren Sie Anfragen, mit denen man die folgenden Fragestellungen beantworten kann: (i) Welche Artikel wurden bestellt? (ii) Wie viele Klammern wurden bestellt? (iii) Welcher Kunde hat eine Waschmaschine bestellt? (iv) Bei welchen Artikeln reicht der Bestand nicht aus, um die Bestellung auszuführen? (v) Wie heißt der Kunde, der einen Trockner bestellt hat? (vi) Gibt es einen Erstbesteller, d. h. einen Besteller, der kein Stammkunde ist? Lösung: Aufgabe 4: a) (i) X = stammkunde(ja) (ii) Anzahl = 10 (iii) A = 4 (Artikelnummer) , X = 2 (Anzahl Bestand) b) (i) bestellung(_,A,_),artikel(A,Artikel,_). (ii) bestellung(_,A,Anzahl),artikel(A,’Klammern’,_). (iii) bestellung(K,1,_),kunde(K,Name,_). (iv) bestellung(_,A,Bestellt),artikel(A,Artikel,Bestand),Bestellt>=Bestand. (v) bestellung(K,2,_),kunde(K,Name,_). (vi) bestellung(K,_,_),kunde(K,_,stammkunde(nein)). Aufgabe 2: Prolog – Rekursion a) Aus der ersten Klausur der Stufe 12 kennen Sie die Funktion f, welche sich wie folgt rekursiv errechnet: f (n − 1) + f (n − 2) − f (n − 3) für n > 2 f ( n) = 2n für 0 ≤ n ≤ 2 Schreiben Sie ein entsprechendes zweistelliges Prädikat f/2. b) Ebenfalls in dieser ersten Klausur der 12 haben Sie eine rekursiv definierte Zeichenfolge kennen gelernt, welche sich wie folgt entwickelt (n = 1, 2, ..., 5). 1, 112, 1121123, 112112311211234, 1121123112112341121123112112345, ... Schreiben Sie ein Prädikat zeichenfolge/2, welches zu einer Zahl n die n-te Zeichenfolge als Liste zurückgibt. Lösung: Aufgabe 2: a) f(0,0). f(1,2). f(2,4) f(N,Ergebnis):- N1 is N-1, N2 is N-2, N3 is N-3, f(N1,Erg1), f(N2,Erg2), f(N3,Erg3), Ergebnis is Erg1+Erg2-Erg3. b) zf(1,[1]). zf(N,Liste):N1 is N – 1, zf(N1, Liste1), append(Liste1,Liste1,Liste2), append(Liste2,[N],Liste). Aufgabe 1: Prolog – Listen a) Sie kennen die Datenstruktur Schlange bzw. Queue. Sie zeichnete sich dadurch aus, dass neue Elemente stets am Ende der „Liste“ eingefügt wurden und am Anfang der Liste gelöscht wurden. Schreiben Sie in Prolog die Methoden empty/1 ; front/2 ; enqueue/3 und dequeue/2 Hinweis: Die Fragestellung empty(L1), enqueue(L1,a,L2), enqueue(L2,b,L3), front(L3,X), dequeue(L3,L4), front(L4,Y). liefert die Antwort: L1 = [] L2 = [a] L3 = [a, b] X = a L4 = [b] Y = b b) Gegeben ist das folgende Prolog-Programm: wti(0,[]). wti(N,[X|Rest]):N1 is N – 1, X is 2 * N, wti(N1,Rest). (i) Welche Antwort gibt Prolog auf die Frage ?- wti(4,Liste). (ii) Welche Antwort gibt Prolog auf die Frage ?- wti(3,[2,4,6]). Begründen Sie. (iii) Welche Antwort gibt Prolog auf die Frage ?- wti(N,[6,4,2]). Begründen Sie. c) In Prolog gibt es das Systemprädikat not(...), welches die Auswertung eines logischen Ausdrucks umdreht. So liefert not(4>9) als Antwort yes. Der Aufruf not(element(3,[1,2,3])) liefert no. Implementieren Sie ein Prädikat liste_zu_menge/2, welches eine Liste in eine Menge überführt. Das heißt, dass Elemente, die in der Liste mehrfach auftreten, in der Menge nur einfach auftauchen. Das oben erwähnte Systemprädikat kann dafür nützlich sein. Beispiel: Der Aufruf liste_zu_menge([2,3,2,1,3],Menge). wird von Prolog mit Menge=[3,1,2] beantwortet. Die Reihenfolge der Elemente in der Menge ist dabei allerdings beliebig. Lösung: Aufgabe 1: a) empty([]). front([X|_],X). dequeue([_|Rs],Rs). enqueue(Ls,X,Qs):- append(Ls,[X],Qs). b) (i) L=[8,6,4,2] (ii) no. richtig wäre [6,4,2] (iii) Variable nicht definiert (N1 is N − 1) c) liste_zu_menge([],[]). liste_zu_menge([X|Liste_rest],Menge):not(element(X,Liste_rest)),liste_zu_menge(Liste_rest,Ergebnis), verknuepft([X],Ergebnis,Menge). liste_zu_menge([X|Liste_rest],Menge):element(X,Liste_rest),liste_zu_menge(Liste_rest,Menge). Aufgabe 1: Logische Programmierung - Prolog a) Aus Ihrer ersten Klausur zum Thema Rekursion kennen Sie noch das kleine Dorf Stonewood. Dort existierte seit jeher ein sehr überschaubares Währungssystem: Als Zahlungsmittel gab es kleine Steine (S) und große Holzstücke (H). Dabei war ein Holzstück genau drei Steine wert. Welche Möglichkeiten der Bezahlung gibt es für einen Stonewood-Einwohner, einen Sack Kartoffeln im Wert von 7 Steinen zu bezahlen? Stellen Sie alle Möglichkeiten dar. Hinweis: Für die Bewohner von Stonewood sind die Möglichkeiten HHS und SHH zwei verschiedene Möglichkeiten, d. h. die Reihenfolge spielt eine Rolle. Implementieren Sie ein Prolog-Prädikat stonewoodcount/2, welches zu einem Betrag X die Anzahl der verschiedenen Möglichkeiten Y berechnet, wie der Betrag X bezahlt werden kann. Ein Programmaufruf würde folgendes Resultat liefern: ?- stonewoodcount(7,C). C = 9 Yes Stellen Sie den rekursiven Abstieg ihres Prädikats für den Aufruf stonewoodcount(7,C) grafisch dar. Beurteilen und begründen Sie die Effizienz Ihres Prolog-Prädikats stonewoodcount/2. Nehmen Sie bei Ihren Ausführungen Bezug auf die grafische Darstellung des rekursiven Abstiegs. Entwickeln Sie ein Prolog-Prädikat stonewood/2, welches zu einem Betrag X alle verschiedenen Möglichkeiten der Bezahlung ausgibt. Ein Aufruf sieht dabei wie folgt aus: ?Ls Ls Ls Ls No stonewood(5,Ls). = [s, s, s, s, s] ; = [s, s, h] ; = [s, h, s] ; = [h, s, s] ; b) Entwickeln Sie zwei verschiedene Versionen eines Prädikats loeschen/3, welches ein Element X aus einer Liste Y löscht und die resultierende Liste Z ohne das Element X zurückgibt. (1) Aus der Liste Y wurde nur das erste auftretende X gelöscht: loeschen(2,[1,2,3,2],L) → L = [1,3,2] (2) Aus der Liste Y wurden alle auftretenden X gelöscht: loeschen(2,[1,2,3,2],L) → L = [1,3] Entwickeln Sie ein Prädikat liste_zu_menge/2, welches eine Liste X in eine Menge Y überführt. Das heißt, dass Elemente, die in der Liste mehrfach auftreten, in der Menge nur einfach auftauchen. Verwenden Sie für die Implementierung das soeben entwickelte Prädikat loeschen/3. Ein Aufruf der Regel könnte wie folgt aussehen: ?- listezumenge([1,2,5,3,2,4,1,2,3,1,4],X). X = [1, 2, 5, 3, 4] ; c) Im Unterricht haben Sie Zahlenrätsel mithilfe von Prolog gelöst. Entwickeln Sie ein Prolog-Programm Raetsel/6, welches das folgende Zahlenrätsel löst. TICK + TRICK + TRACK --------=ATICKI d) Gegeben ist folgendes Prolog-Programm, welches eine Liste Xs sortiert und in Ys zurückgibt. sortiert(Xs,Ys):- permutiert(Xs,Ys), geordnet(Ys). geordnet([_]). geordnet([X,Y|Zs]):- X =< Y, geordnet([Y|Zs]). ausgewaehlt(X,[X|Xs],Xs). ausgewaehlt(Y,[X|Xs],[X|Zs]):- ausgewaehlt(Y,Xs,Zs). permutiert([],[]). permutiert(Xs,[Z|Zs]):- ausgewaehlt(Z,Xs,Ys), permutiert(Ys,Zs). Erläutern Sie die Funktionsweise des Sortierverfahrens. Analysieren Sie die Effizienz dieses Sortierverfahrens. e) Gegeben ist der rechts abgebildete Graph. E Stellen Sie die Informationen mithilfe eines Prädikats benachbart/3 dar. Achten Sie darauf, dass der Graph symmetrisch ist. F 6,3 11,1 17,8 A 2,9 3,4 B 3,0 Entwerfen Sie ein Prädikat verbunden/2, welches prüft, ob es einen Weg zwischen zwei vorgegebenen Knoten X und Y gibt. 11,7 1,2 C D Erweitern Sie das Prädikat verbunden/2 zu einem dreistelligen Prädikat kosten/3, welches die Kosten des Weges zwischen zwei vorgegebenen Punkten berechnet. Hinweis: Das Prädikat muss nicht den kürzesten Weg finden! f) Die Datenstruktur Ternärbaum hat folgende Eigenschaften: 1) Jeder Knoten hat zwei Zahlen 2) Jeder Knoten hat drei Nachfolger, welche auch nil sein können. 3) Die erste Zahl ist größer als alle Zahlen des linken Teilbaums und kleiner als alle Zahlen des mittleren Teilbaums. Die rechte Zahl ist größer als alle Zahlen des mittleren Teilbaums und kleiner als alle Zahlen 17 35 des rechten Teilbaums. Ein Beispiel eines Ternärbaums sehen Sie rechts abgebildet. Einen leeren Baum stellen wir in Prolog durch die Konstante nil dar, einen nichtleeren Baum durch das fünfstellige Prädikat 11 7 9 14 23 29 26 28 47 50 baum(linkerTeilbaum,linkesElement,mittlererTeilbaum,rechtesElement,rechterTeilbaum). Bearbeiten Sie zu dieser Datenstruktur folgende Aufgabenteile: Stellen Sie den Baum grafisch dar, der durch folgendes Prädikat gegeben ist: baum(baum(nil,5,nil,8,baum(nil,11,nil,17,nil)),39,nil,40,baum(nil,51,nil,57,nil)) G Stellen Sie den Beispiel-Baum als Prolog-Prädikat dar. Implementieren Sie das Prädikat enthalten/2, welches überprüft, ob das Element X im Baum Y enthalten ist. Sie können davon ausgehen, dass die Elemente im Baum sortiert angeordnet sind. Implementieren Sie ein Prädikat baum_zu_liste/2, welches die Zahlen des Baumes X in eine sortierte Liste Y überführt. Aufgabe 1: Logische Programmierung – Prolog-Grundlagen a) In einer Schule gibt es folgende Schüler, die die in Klammern angegebenen Fächer belegen: Philipp(Mathematik, Chemie), Markus(Mathematik, Musik, Englisch), Alexander(Biologie, Chemie, Sport), Felix(Sport) und Timo(Informatik, Mathematik). Außerdem unterrichten folgende Lehrer die in Klammern angegeben Fächer: Frau Lauert(Biologie, Chemie), Frau Michaelis(Musik), Herr Fischer(Mathematik, Physik) und Herr Krause(Sport, Geographie). I) Bilden Sie eine Prologdatenbasis, die die oben genannten Fakten in Form der beiden Relationen belegt(Schüler, Fach) und unterrichtet(Lehrer, Fach) enthält. II) Formulieren Sie folgende Anfragen in Prolog! 1. Welche Schüler belegen Mathematik? 2. Von welchen Lehrern wird Philipp unterrichtet? 3. Gibt es einen Lehrer, der Alexander und Felix unterrichtet? 4. Hat Timo einen Mitschüler, der dasselbe Fach wie Alexander belegt? 5. Welche Lehrer unterrichten denselben Schüler? 6. Welche Lehrer unterrichten mehr als zwei Schüler? Dabei sind zwei Schüler Mitschüler, wenn sie dasselbe Fach belegen. b) An einem Tisch sitzen so wie rechts abgebildet sechs Personen. Halpaap Ciolek I) Erstellen Sie ein Prolog-Programm, welches die dargestellte Situation mithilfe des Prädikats sitztRechtsNeben/2 beschreibt. II) Gierschke Formulieren Sie Anfragen in Prolog, mit deren Hilfe man folgende Informationen erhält: 1. Wer sitzt rechts neben Soworka? 2. Von wem ist Halpaap der rechte Nachbar? 3. Wer sitzt links neben May? 4. Welche Nachbarn hat Ciolek? 5. Wer sitzt Gierschke gegenüber? 6. Wer sitzt links neben dem rechten Nachbarn von Büßelmann? Soworka Büßelmann May III) Erweitern Sie das Programm aus I um die Prädikate sitztLinksNeben/2, sitztGegenueber/2, und hatNachbarn/3, wobei die Prädikate alle auf das Prädikat sitztRechtsNeben/2 Bezug nehmen sollen. Lösung: Aufgabe 1 a.I) belegt(philipp,mathematik). belegt(philipp,chemie). belegt(markus,mathematik). belegt(markus,musik). belegt(markus,englisch). belegt(alexander,biologie). belegt(alexander,chemie). belegt(alexander,sport). belegt(felix,sport). belegt(timo,informatik). belegt(timo,mathematik). unterrichtet(lauert,chemie). unterrichtet(lauert,biologie). unterrichtet(michaelis,musik). unterrichtet(fischer,mathematik). unterrichtet(fischer,physik). unterrichtet(krause,sport). unterrichtet(krause,geographie). a.II) 1. ?- belegt(X,mathematik). 2. ?- unterrichtet(X,Y), belegt(philipp,Y). 3. ?- unterrichtet(L,Fach), belegt(felix,Fach), belegt(alexander,Fach). 4. ?- belegt(timo,Fach), belegt(X,Fach), belegt(X,Fach2), belegt(alexander,Fach2). 5. ?- unterrichtet(L1,Fach1), unterrichtet(L2,Fach2), belegt(X,Fach1), belegt(X,Fach2), L1\=L2. 6. ?- unterrichtet(L,F), belegt(X,F), belegt(Y,F), belegt(Z,F), X\=Y, Y\=Z, X\=Z. b.I) sitztRechtsNeben(halpaap, ciolek). sitztRechtsNeben(ciolek, gierschke). sitztRechtsNeben(gierschke, may). sitztRechtsNeben(may,buesselmann). sitztRechtsNeben(buesselmann,soworka). sitztRechtsNeben(soworka,halpaap). b.II) 1. ?- sitztRechtsNeben(soworka,X). 2. ?- sitztRechtsNeben(X,halpaap). 3. ?- sitztRechtsNeben(X,may). 4. ?- sitztRechtsNeben(ciolek,X); sitztRechtsNeben(X,ciolek). 5. ?- sitztRechtsNeben(gierschke,X), sitztRechtsNeben(X,Y), sitztRechtsNeben(Y,Z). 6. ?- sitztLinksNeben(buesselmann,X), sitztRechtsNeben(Y,X). b.III) sitztLinksNeben(A,B):- sitztRechtsNeben(B,A). sitztGegenueber(A,B):- sitztRechtsNeben(A,X), sitztRechtsNeben(X,Y), sitztRechtsNeben(Y,B). hatNachbarn(A,B,C):- sitztRechtsNeben(B,A), sitztRechtsNeben(A,C). Aufgabe 2: Logische Programmierung – Prolog-Rekursion/Listen a) Aus Ihrer ersten Klausur zum Thema Rekursion kennen Sie noch das Profi-Nim-Spiel. Beim diesem Spiel liegen n Streichhölzer in der Mitte und die Spieler nehmen abwechselnd entweder ein oder aber drei Hölzer weg. Das Spiel endet, wenn das letzte Streichholz genommen wurde. I) Welche möglichen Spielverläufe gibt es, wenn das Spiel mit n = 7 Streichhölzern gestartet wird? Stellen Sie alle Möglichkeiten dar. Hinweis: Ein möglicher Spielverlauf wäre z. B. 1−3−1−1−1. Der Spielverlauf 1−1−1−3−1 ist ebenfalls ein eigenständiger Spielverlauf. II) Implementieren Sie ein Prolog-Prädikat moeglichkeiten/2, welches zu einer anfänglichen Anzahl Streichhölzer (N) die Anzahl der verschiedenen Möglichkeiten M berechnet. Ein Programmaufruf würde folgendes Resultat liefern: ?- moeglichkeiten(5,M). M = 4 Yes Hinweis: Die Anzahl der Möglichkeiten berechnet sich durch die rekursive Funktion 1 n<3 f ( n) = f (n − 1) + f (n − 3) n ≥ 3 III) Stellen Sie den rekursiven Abstieg ihres Prädikats für den Aufruf moeglichkeiten(7,M) grafisch dar. IV) Beurteilen und begründen Sie die Effizienz Ihres Prolog-Prädikats moeglichkeiten/2. Nehmen Sie bei Ihren Ausführungen Bezug auf die grafische Darstellung des rekursiven Abstiegs. V) Entwickeln Sie ein Prolog-Prädikat spielverlauf/2, welches zu einer Anzahl Streichhölzer (N) alle verschiedenen Möglichkeiten der Spielverläufe in Form einer Liste (Ls) ausgibt. Ein Aufruf sieht dabei wie folgt aus: ?Ls Ls Ls Ls No spielverlauf(5,Ls). = [1, 1, 1, 1, 1] ; = [1, 1, 3] ; = [1, 3, 1] ; = [3, 1, 1] ; b) In dem rechts abgebildeten Labyrinth soll ein Weg von Raum A nach Raum G gesucht werden. I) Stellen Sie die Informationen des Labyrinths als Prolog-Fakten dar. Definieren Sie dafür ein Prädikat tuer/2, welches die Existenz einer Verbindungstür zwischen zwei Räumen angibt. Achtung! Es existiert eine Tür zwischen A und B, aber auch eine Tür zwischen B und A. II) Analysieren Sie das Prädikat suche/3. Erläutern Sie, warum es Prolog so nicht möglich ist, einen Weg von A nach G zu finden. (Aufrruf: suche(a,g,Weg) ) suche(X,Y,[X,Y]):- tuer(X,Y). suche(X,Y,[X|Weg]):- tuer(X,Z), suche(Z,Y,Weg). A D G B E H C F I III) Begründen Sie, welches Ziel mit der Einführung des vierten Parameters verfolgt wird. (Aufruf: suche(a,g,Weg,[a]) ). Prolog würde mit dieser Änderung nämlich einen korrekten Weg = [a, b, e, f, i, h, g] (und auch einen zweiten Weg) ausgeben. suche(X,Y,[X,Y],Hilf):tuer(X,Y), not(element(Y,Hilf)). suche(X,Y,[X|Weg],Hilf):- tuer(X,Z), not(element(Z,Hilf)), suche(Z,Y,Weg,[Z|Hilf]). Hinweis: In Prolog gibt es das Systemprädikat not(...), welches die Auswertung eines logischen Ausdrucks umdreht. So liefert not(4>9) als Antwort yes. Der Aufruf not(element(3,[1,2,3])) liefert no. Das Prädikat element/2 kennen Sie aus dem Unterricht. Lösung: Aufgabe 2: a.I) 1-1-1-1-1-1-1 1-1-1-1-3 1-1-1-3-1 1-1-3-1-1 1-3-1-1-1 1-3-3 3-1-1-1-1 3-1-3 3-3-1 a.II) moeglichkeiten(X,1):- X=<2,X>=0. moeglichkeiten(X,Y):- X>2, X1 is X -1, moeglichkeiten(X1,Y1),X2 is X-3, moeglichkeiten(X2,Y2), Y is Y1+Y2. a.III) In der folgenden Darstellung entspricht f(X)=Y dem Prädikataufruf moeglichkeiten(X,Y) f(7) =9 f(6) f(5) =4 =6 f(4) =3 f(3) =2 f(3) =2 f(1) =1 f(4) f(3) =2 =3 f(2) =1 f(2) =1 f(0) =1 f(2) =1 f(0) =1 f(1) =1 f(2) =1 f(0) =1 a.IV) Uneffizient, da Berechnungen teilweise mehrfach durchgeführt werden. Z. B. muss der Aufruf moeglichkeiten(4,M) zwei mal, der Aufruf moeglichkeiten(3,M) sogar 3 mal durchgeführt werden. Die Zunahme des Parameters N um 1 bewirkt eine annähernde Verdopplung der Berechnungsschritte. => Laufzeit O(2n). a.V) spielverlauf(0,[]). spielverlauf(X,[1|Rs]):- X>0, X1 is X - 1, spielverlauf(X1,Rs). spielverlauf(X,[3|Rs]):- X>2, X1 is X - 3, spielverlauf(X1,Rs). b.I) tuer(a,b). tuer(c,f). tuer(f,i). tuer(b,a). tuer(f,c). tuer(i,f). tuer(b,c). tuer(d,e). tuer(g,h). tuer(c,b). tuer(e,d). tuer(h,g). tuer(b,e). tuer(e,f). tuer(h,i). tuer(e,b). tuer(f,e). tuer(i,h). b.II) Das erste Prädikat gibt an, dass ein Weg zwischen X und Y existiert, wenn eine Tür zwischen X und Y existiert. Der Weg besteht dann aus den beiden Räumen X und Y. Das zweite Prädikat wird nur dann gewählt, wenn es keine Tür von X nach Y gibt. Dann wird ein benachbarter Raum von X gewählt (hier Z) und versucht, von Z aus einen Weg nach Y zu suchen. Der Weg wird in diesem Fall um den jetzt besuchten Raum X erweitert. Prolog startet mit Tuer A-B. von B aus wird die Tür B-A getestet. Von dort wird die Tuer AB gewählt, dann Tür B-A, usw.. Prolog läuft also in eine endlose Rekursion. b.III) Der vierte Parameter hat das Ziel, alle besuchten Räume in einer Liste zu speichern. Will man den Weg von in eine Richtung fortsetzen, so ist dies nur möglich, wenn der neu zu besuchende Raum nicht schon vorher besucht wurde. Aufgabe 1: Logische Programmierung – Prolog a) Gegeben ist folgendes Prolog-Programm, welches eine Liste Liste sortiert und in ListeS zurückgibt. sortiert([],[]). sortiert(Liste,ListeS):- sucheelement(Liste,X,Restliste), sortiert(Restliste,RestlisteS), append(RestlisteS,[X],ListeS). sucheelement([X],X,[]). sucheelement([K|Rs],K,Rs):- sucheelement(Rs,M,_), M=<K. sucheelement([K|Rs],M,[K|Zs]):- sucheelement(Rs,M,Zs), M>K. I) Erläutern Sie die Funktionsweise des Sortierverfahrens und geben Sie ihm den richtigen Namen. II) Kommentieren Sie die einzelnen Programmzeilen sinnvoll b) Gegeben ist die folgende Prolog-Datenbank: %kunde(Kundennr, name(Vorname, Nachname), adresse(Strasse, Hausnummer, PLZ), Stammkunde?). kunde(13, name("Alfred", "Vogel"), adresse("Starenweg",7,51519), stammkunde(ja)). kunde(16, name("Berta", "Müller"), adresse("Mühlenweg",2,51519), stammkunde(nein)). kunde(27, name("Claus", "Bauer"), adresse("Landwehrweg",9,51467), stammkunde(ja)). kunde(33, name("Doris", "Wassermann"), adresse("Stauseestr.",6,51469), stammkunde(ja)). %orte(PLZ, Ort, Lieferung möglich) orte(51519,"Odenthal",lieferung(ja)). orte(51467,"Bergisch Gladbach",lieferung(ja)). orte(51469,"Bergisch Gladbach",lieferung(nein)). %artikel(Artikelnummer, Artikelname, Hersteller, Preis in €) artikel(19, "Tomatensuppe", "Knoll", 0.79). artikel(98, "Möhreneintopf", "Manni", 1.39). artikel(66, "Cornflakes", "Kellys", 1.99). artikel(35, "Spaghetti", "basilla", 0.35). %bestellung(Kundennr, bestellung(13, 19, 5, bestellung(13, 35, 2, bestellung(16, 98, 6, bestellung(33, 19, 2, bestellung(27, 35, 1, I) II) Artikelnr, Anzahl, Lieferwunsch?) ja). ja). nein). ja). nein). Geben Sie die Antwort von Prolog auf folgende Anfragen an: 1. kunde(_,Name,adresse(_,_,51519),_). 2. artikel(Nr,_,_,Preis), Preis < 1.00. 3. bestellung(Kunde,_,_,ja),kunde(Kunde,_,_,stammkunde(ja)). Formulieren Sie Anfragen, mit denen man die folgenden Fragestellungen beantworten kann 1. Welche Stammkunden (Name und Adresse) wohnen in Odenthal? 2. Welche Artikel (Herstellername) werden bestellt? 3. Welcher Kunde (Kundennummer) möchte beliefert werden, wohnt aber in einem Ort, der nicht beliefert wird? c) Quadratische Schwarz-Weiß-Grafiken, deren Seitenlänge (in Pixeln) eine Zweierpotenz ist, können mit Hilfe der Datenstruktur QuadTree gespeichert werden. Ein QuadTree ist dabei ein Baum, der entweder vier Teilbäume hat oder ein Blatt ist. Der Inhalt eines Bildes wird nach folgendem Algorithmus in der Datenstruktur abgelegt: • Jedem Teilquadrat der Grafik entspricht ein QuadTree. • Ist die Farbe eines Teilquadrates einheitlich, so wird in den Knoten des zugehörigen QuadTree der Farbwert (1 = schwarz, 0 = weiß) eingetragen. Der QuadTree besitzt in diesem Fall leere Teilbäume und ist somit ein Blatt. • Ist die Farbe nicht einheitlich, so wird dies im Knoten des zugehörigen QuadTree durch den Wert −1 kenntlich gemacht. Anschließend wird das Quadrat in vier Teilquadrate zerlegt. Deren Bildinhalte werden im Uhrzeigersinn (links oben (LO), rechts oben (RO), rechts unten (RU), links unten (LU)) in Teilbäume abgelegt und an den aktuellen Knoten angehängt. Beispiel: Folgendes 8×8-Schwarz-Weiß-Bild soll in einem QuadTree gespeichert werden: Der zugehörige QuadTree sieht demnach wie folgt aus: −1 −1 1 −1 1 −1 0 0 0 0 0 0 0 0 1 −1 0 0 1 0 −1 0 1 0 0 Einen leeren Baum stellen wir in Prolog durch die Konstante nil dar, einen nichtleeren Baum durch das fünfstellige Prädikat baum(farbwert,teilbaumLO,teilbaumRO,teilbaumRU,teilbaumLU). Bearbeiten Sie zu dieser Datenstruktur folgende Aufgabenteile: I) Zeichnen Sie den Baum, der durch folgendes Prädikat gegeben ist: baum(-1,baum(1,nil,nil,nil,nil), baum(-1, baum(0,nil,nil,nil,nil), baum(1,nil,nil,nil,nil), baum(0,nil,nil,nil,nil), baum(1,nil,nil,nil,nil)), baum(0,nil,nil,nil,nil), baum(1,nil,nil,nil,nil)) II) Zeichnen Sie die zugehörige 4×4-Grafik, welche in diesem Baum gespeichert ist. III) Stellen Sie die rechts abgebildete Grafik als Baum dar. IV) Geben sie ein Prädikat an, welches diesen Baum repräsentiert. V) Implementieren Sie ein Prolog-Prädikat knotenanzahl/2, welches die Anzahl der Knoten eines QuadTrees berechnet. Durchläuft man den Beispiel-Baum in der Reihenfolge Wurzel-Linksaußen-LinksinnenRechtsinnen-Rechtsaußen, so erhält man die untenstehende Folge von Knoteninhalten, die als Bilddatei gespeichert werden könnte: −1, −1, −1, 1, 0, 0, 0, 0, 0, 0, 1, −1, 0, 0, 1, 0, −1, 0, 1, 0, −1, 0, 1, 0, 0 VI) Analysieren Sie das Prädiket listeZuBaum/3, welches zu einer Liste der oben angegebenen Art wieder einen Baum rekonstruiert und zurückgibt. Kommentieren und begründen Sie die einzelnen Programmzeilen. Gehen Sie dabei insbesondere auf die Notwendigkeit des zweiten Parameters ein. listeZuBaum([],[],nil). listeZuBaum([F|Rest],Rest,baum(F,nil,nil,nil,nil)):- F>=0. listeZuBaum([-1|Rest],NeuRest,baum(-1,LO,RO,RU,LU)):listeZuBaum(Rest,Rest1,LO), listeZuBaum(Rest1,Rest2,RO), listeZuBaum(Rest2,Rest3,RU), listeZuBaum(Rest3,NeuRest,LU). Lösung: Aufgabe 1: a) I) Das Programm sortiert nach dem Verfahren Selection-Sort, dabei wird stets das größte Element des unsortierten Bereichs herausgesucht und an das Ende angefügt. II) 1. Rekursions-Anker: eine leere Liste ist sortiert. 2. Eine Liste wird sortiert, indem man das größte Element heraussucht, den Rest sortiert und dann das größte Element hinten anfügt. 3. Das größte Element einer einelementigen Liste ist das einzige Element. 4. Das größte Element einer Liste ist das Kopfelement, wenn im Rest kein größeres gefunden wird. 5. Das größte Element ist das größte Element der Restliste, wenn das Kopfelement kleiner als dieses ist. b) I) II) c) 1. Alle Kunden-Namen, die im PLZ-Bereich 51519 wohnen. Name = name("Alfred","Vogel") Name = name("Berta", "Müller") 2. Alle Artikel-Nummern und -Preise, deren Preis kleiner als 1 € ist. Nr = 19 Preis = 0.79 Nr = 35 Preis = 0.35 3. Alle Stammkunden-Nummern, die ihre Bestellung geliefert haben wollen. Kunde = 13 Kunde = 13 Kunde = 33 1. kunde(_,Name,adresse(Strasse,PLZ),stammkunde(ja)), orte(PLZ,"Odenthal"). 2. bestellung(_,ArtNr,_,_), artikel(ArtNr,_,Hersteller,_). 3. kunde(KdNr,_,adresse(_,_,PLZ),_),bestellung(KdNr,_,_,ja),orte(PLZ,_,lieferung(nein)). I) –1 1 0 −1 0 1 1 0 1 II) Zeichnen Sie die zugehörige 4×4-Grafik, welche in diesem Baum gespeichert ist. III) –1 1 0 1 0 −1 1 1 0 IV) baum(-1, baum(1, nil, nil, nil, nil), baum(0, nil, nil, nil, nil), baum(-1, baum(1, nil, nil, nil, baum(1, nil, nil, nil, baum(1, nil, nil, nil, baum(0, nil, nil, nil, baum(0, nil, nil, nil, nil)) nil), nil), nil), nil)), V) %quadtreeknotenanzahl(B,A):- B: Baum, A: Anzahl quadtreeknotenanzahl(nil,0). quadtreeknotenanzahl(baum(F,B1,B2,B3,B4),A):quadtreeknotenanzahl(B1,A1),quadtreeknotenanzahl(B2,A2), quadtreeknotenanzahl(B3,A3),quadtreeknotenanzahl(B4,A4), A is A1 + A2 + A3 + A4 + 1. VI) 1. Eine leere Liste erzeugt einen leeren Baum. 2. Ist im der Liste am Kopf ein Farbwert (1/0), gespeichert, so wird dieser gelöscht (zweiter Parameter ohne Kopf) und ein Blatt wird erzeugt. 3. Ist imKopf der Liste eine –1 gespeichert, so wird aus dem Rest der äußerst-linkeTeilbaum erzeugt und die Inhalte aus der Liste gelöscht. Mit dem Rest wird der linke-innere-Teilbaum erstellt und die Inhalte aus der Liste gelöscht. Dann der rechte-Innere-Teilbaum und zum Schluss der äußerst-rechte-Teilbaum. aus der ursprünglichen Liste sind alle Elemente für diesen Baum gelöscht. Der neue Rest wird in NeuRest zurückgegeben. Aufgabe 3: Prolog a) Geben Sie das Ergebnis an, welches Prolog auf folgende Anfragen ausgibt: I) [E|Rs] = [a,b,c,d] II) [A,b|[C,d,E]] = [a,b,c,d,e] III) [A,B|Ende] = [[1,2],[3,4,5]] IV) [E,Rs] = [] b) Gegeben ist die folgende Datenbasis: stadt(duesseldorf). stadt(koeln). stadt(trier). stadt(frankfurt). stadt(dortmund). stadt(muenster). stadt(hamburg). stadt(stuttgart). verbindung(koeln, duesseldorf). verbindung(koeln, trier). verbindung(koeln, frankfurt). verbindung(duesseldorf, dortmund). verbindung(dortmund, muenster). verbindung(frankfurt, stuttgart). verbindung(hamburg, münster). verbindung(koeln, dortmund). I) II) Wir wollen herausfinden, ob es eine Verbindung zwischen Stuttgart und Hamburg gibt. Begründen Sie, dass diese Datenbasis in vorliegender Form noch nicht besonders gut geeignet ist, um diese Aufgabe zu erfüllen. Erweitern Sie anschließend die Datenbasis um hilfreiche Fakten. Entwickeln Sie dann ein Prädikat gibtVerbindung/2, mit dem man feststellen kann, ob es zwischen zwei beliebigen Orten X und Y eine Verbindung gibt. Gegeben ist das folgende Prädikat: bildenDreieck(A, B, C):- stadt(A), stadt(B), stadt(C), write(A), write(B), write(C), nl, verbindung(A,B), verbindung(A,C), verbindung(B,C). Geben Sie die Ausgabe bei folgender Anfrage an: bildenDreieck(koeln, X, Y). c) Gegeben seien drei Relationen mit den folgenden Daten: Besucht Serviert Mag Gast Bistro Bistro Getränk Gast Getränk Hans Uno Uno Wasser Hans Wasser Ede Uno Uno Kaffee Ede Wasser Ede Dos Dos Kaffee Ede Kaffee Ede Chico Karl Kaffee Karl Dos Karl Chico Heini Uno I) Implementieren Sie ein äquivalentes Prolog-Programm mit diesen Fakten. II) Geben Sie die Anfrage an, mit der alle Getränke ausgegeben werden, die in dem Bistro serviert werden, welches Karl besucht. III) Gesucht sind alle Gäste, die ein Bistro besuchen, das auch das Getränk serviert, das sie mögen. Formulieren Sie eine entsprechende Prolog-Anfrage. d) An einem Tisch sitzen so wie rechts abgebildet acht Personen. I) Erstellen Sie ein Prolog-Programm, welches die dargestellte Situation mithilfe des Prädikats sitztRechtsNeben/2 beschreibt. II) Dennis Jean Jens Kristina Formulieren Sie Anfragen in Prolog, mit deren Hilfe Tizian man folgende Informationen erhält: 1. Wer sitzt rechts neben Jean? 2. Von wem ist Matthias der rechte Nachbar? 3. Wer sitzt links neben Tizian? 4. Welche Nachbarn hat Moritz? 5. Wer sitzt Kristina gegenüber? 6. Wer sitzt links neben dem rechten Nachbarn von Frederik? Matthias Moritz Frederik III) Erweitern Sie das Programm aus I um die Prädikate sitztLinksNeben/2, sitztGegenueber/2, und hatNachbarn/3, wobei die Prädikate alle auf das Prädikat sitztRechtsNeben/2 Bezug nehmen sollen. Lösung: Aufgabe 3 a) I) E = a Rs = [b,c,d] II) A = a C = c E = e III) A = [1,2] B = [3,4,5] IV) no / false b) I) Ende = [] Das Prädikat verbindung/2 ist nicht in beide Richtungen gerichtet. verbindung(duesseldorf, koeln). verbindung(trier, koeln). etc. und schließlich die Verbindung rekursiv: gibtVerbindung(X,Y):- verbindung(X,Y). gibtVerbindung(X,Y):- verbindung(X,Z), gibtVerbindung(Z,Y). II) c) Die Ausgabe lautet: koelnduesseldorfduesseldorf koelnduesseldorfkoeln koelnduesseldorftrier koelnduesseldorffrankfurt koelnduesseldorfdortmund X = duesseldorf, Y = dortmund I) besucht(hans, uno). besucht(ede, uno). besucht(ede,dos). besucht(ede,chico). besucht(karl,dos). besucht(karl,chico). besucht(heini,uno). serviert(uno, wasser). serviert(uno, kaffee). serviert(dos, kaffee). mag(hans, wasser). mag(ede, wasser). mag(ede,kaffee). mag(karl,kaffee). II) besucht(karl,Bistro), serviert(Bistro, Getränk). III) besucht(Gast,Bistro), mag(Gast, Getränk), serviert(Bistro, Getränk). d) I) II) III) % sitztRechtsNeben(X,Y):- X sitzt rechts neben Y sitztRechtsNeben(dennis, jens). sitztRechtsNeben(jens, matthias). sitztRechtsNeben(matthias, moritz). sitztRechtsNeben(moritz, frederik). sitztRechtsNeben(frederik, tizian). sitztRechtsNeben(tizian,kristina). sitztRechtsNeben(kristina,jean). sitztRechtsNeben(jean,dennis). 1. sitztRechtsNeben(X,jean). 2. sitztRechtsNeben(matthias,Y). 3. sitztRechtsNeben(tizian,Links). 4. sitztRechtsNeben(moritz,Links); sitztRechtsNeben(Rechts,moritz). 5. sitztRechtsNeben(X,kristina), sitztRechtsNeben(Y,X), sitztRechtsNeben(Z,Y), sitztRechtsNeben(Y,Gegenüber). 6. sitztRechtsNeben(X,frederik), sitztRechtsNeben(X,Links). sitztLinksNeben(X,Y):- sitztRechtsNeben(Y,X). sitztGegenüber(A,B):- sitztRechtsNeben(X,A), sitztRechtsNeben(Y,X), sitztRechtsNeben(Z,Y), sitztRechtsNeben(Z,B). hatNachbarn(X,Y,Z):- sitztRechtsNeben(X,Y); sitztRechtsNeben(Z,X). Aufgabe 4: Prolog − Rekursion Die Raum- und Gebäudeordnung einer Schule sei wie folgt gegliedert: Schule: gymnasium Gebäude: aula Trakt: Raum: neubau altbau turnhalle 501 502 pavillon geräte 811 6erTurm 913 613 615 1erTurm 105 118 a) Stellen Sie die Fakten dieser Gliederung in Form eines zweistelligen Prädikats istIn/2 dar. Z. B. sollte istIn(501, turnhalle) den Wert true ausgeben. Stellen Sie lediglich die direkten Beziehungen, also die Beziehungen, die über genau eine Kante bestehen, in dem Prädikat dar. b) Formulieren Sie Prolog-Anfragen für folgende Fragestellungen: i) Welche Räume hat der Pavillon? ii) Befindet sich der Raum 811 im Neubau-Gebäude? iii) Sind der Geräteraum und der Raum 913 im gleichen Gebäude? iv) Welche Trakte hat die Schule "Gymnasium" v) Sind die Trakte Turnhalle und 1erTurm in der gleichen Schule? c) Implementieren Sie ein Prädikat istTeilVon/2, welches angibt, ob ein Raum/Trakt/Gebäude Teil eines Traktes/eines Gebäudes/einer Schule ist. Das Prädikat soll auch für Beziehungen erfüllt sein, die über mehr als eine Kante bestehen. d) Implementieren Sie ein Prädikat istTeilVon/3, welches nun zusätzlich zum Aufgabenteil c angibt, über welche Ecken die Beziehung gilt. Die Eckpunkte sollen in Form einer Liste ausgegeben werden. Beispiele: istTeilVon(501, neubau, Liste) liefert Liste = [501, turnhalle, neubau]. istTeilVon(913, altbau, Liste) liefert false. istTeilVon(118, 1erTurm, Liste) liefert Liste = [118, 1erTurm]. e) Die Klassenräume des Turnhallen-Trakts sollen gestrichen werden. Dabei sollen jeweils zwei aneinander angrenzende Klassenräume mit einer unterschiedlichen Farbe gestrichen werden. Es stehen die Farben rot, gelb, grün und blau zur Auswahl. Geben Sie ein vollständiges Prolog-Programm an, mithilfe dessen man eine gültige Färbung der Klassenräume ermitteln kann. 501 503 504 502 Lösung: Aufgabe 4: Prolog - Rekursion 505 a) istIn(501, turnhalle). istIn(502, turnhalle). istIn(geräte, turnhalle). istIn(811, pavillon). istIn(913, pavillon). istIn(613,6erTurm). istIn(615, 6erTurm). istIn(105, 1erTurm). istIn(118, 1erTurm). istIn(turnhalle, neubau). istIn(pavillon, neubau). istIn(6erTurm, altbau). istIn(1erTurm, altbau). istIn(aula, gymnasium). istIn(neubau, gymnasium). istIn(altbau, gymnasium). b) i) istIn(X, pavillon). ii) istIn(811, X), istIn(X, neubau). iii) istIn(geräte, X), istIn(X,Y), istIn(913, Z), istIn(Z,Y). iv) istIn(X, gymnasium), istIn(Trakt,X). v) istIn(1erTurm, X), istIn(X, Y), istIn(turnhalle, Z), istIn(Z,Y). c) istTeilVon(X, Y):- istIn(X,Y). istTeilVon(X,Y):- istIn(X,Z), istTeilVon(Z,Y). d) istTeilVon(X, Y, [X,Y]):- istIn(X,Y). istTeilVon(X,Y, [X|Liste]):- istIn(X,Z), istTeilVon(Z,Y,Liste). e) farbe(rot). farbe(blau). farbe(gelb). farbe(grün). faerbung(R1, R2, R3, R4, R5):- farbe(R1) farbe(R2), R1 \= R2, farbe(R3), R3 \= R1, R3\= R2, farbe(R4), R4 \? R1, R4\= R2, R4 \= R3, farbe(R5), R5\= R1, R5 \= R2, R5 \= R4. Aufgabe 4: Prolog Aus Ihrer ersten Klausur zum Thema Rekursion kennen Sie noch das sehr überschaubare Währungssystem aus dem Murmelland: Als Zahlungsmittel gab es kleine Murmeln (K), mittlere Murmeln (M) und große Murmeln (G). Dabei war eine große Murmel genau zwei mittlere Murmeln wert (G = 2M) und eine mittlere Murmel war genau zwei kleine Murmeln wert (M = 2K). Natürlich galt dann auch, dass eine große Murmel genau 4 kleine Murmeln wert war (G = 4K). a) Ein Murmelländer kauft einen Kopfsalat, das insgesamt 5 K wert ist. Geben Sie die verschiedenen Möglichkeiten an, die der Murmelländer hat, um den Kopfsalat zu bezahlen. Hinweis: Für die Bewohner von Murmelland sind die Möglichkeiten MMK und MKM zwei verschiedene Möglichkeiten, d. h. die Reihenfolge spielt eine Rolle. b) Implementieren Sie ein Prolog-Prädikat anzahl/2, welches zu einem Währungsbetrag N (in kleinen Kugeln) die Anzahl der verschiedenen Möglichkeiten der Bezahlung M berechnet. Ein Programmaufruf würde folgendes Resultat liefern: ?- anzahl(4,M). M = 6 Hinweis: Die Anzahl der Möglichkeiten berechnet sich durch die rekursive Funktion 1 N ≤1 f (N ) = N 2≤ N ≤3 f ( N − 1) + f ( N − 2) + f ( N − 4) N >3 c) Stellen Sie den rekursiven Abstieg ihres Prädikats für den Aufruf anzahl(5,M) grafisch dar. d) Beurteilen und begründen Sie die Effizienz Ihres Prolog-Prädikats anzahl/2. Nehmen Sie bei Ihren Ausführungen Bezug auf die grafische Darstellung des rekursiven Abstiegs. e) Entwickeln Sie ein Prolog-Prädikat moeglichkeiten/2, welches zu einem Währungsbetrag N (in kleinen Kugeln) alle verschiedenen Möglichkeiten der Bezahlung in Form einer Liste ausgibt. Ein Aufruf sieht dabei wie folgt aus: ?- moeglichkeiten(4,Liste). Liste = [k, k, k, k] ; Liste = [k, k, m] ; Liste = [k, m, k] ; Liste = [m, k, k] ; Liste = [m, m] ; Liste = [g]