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]