Programmierung WS14/15 Übungsblatt 11 (Abgabe 28.01.2015) Prof.aa Dr. J. Giesl C. Aschermann, F. Frohn, J. Hensel, T. Ströder Allgemeine Hinweise: Hausaufgaben sollen in Gruppen von je 2 Studierenden aus der gleichen Kleingruppenübung (Tutorium) bearbeitet werden. Namen und Matrikelnummern der Studierenden sind auf jedes Blatt der Abgabe zu schreiben. Heften bzw. tackern Sie die Blätter! Die Die Nummer der Übungsgruppe muss links oben auf das erste Blatt der Abgabe geschrieben werden. Notieren Sie die Gruppennummer gut sichtbar, damit wir besser sortieren können. Die Lösungen müssen bis Mittwoch, den 28.01.2015 um 15:00 Uhr in den entsprechenden Übungs- kasten eingeworfen werden. Sie nden die Kästen am Eingang Halifaxstr. des Informatikzentrums (Ahornstr. 55). Alternativ können Sie die Lösungen auch vor der Abgabefrist direkt bei Ihrer Tutorin/Ihrem Tutor abgeben. In einigen Aufgaben müssen Sie in Haskell oder Prolog programmieren und .hs- bzw. .pl-Dateien anlegen. Drucken Sie diese aus und schicken Sie sie per E-Mail vor Mittwoch, dem 28.01.2015 um 15:00 Uhr an Ihre Tutorin/Ihren Tutor. Stellen Sie sicher, dass Ihr Programm von GHC bzw. SWI akzeptiert wird, ansonsten werden keine Punkte vergeben. Tutoraufgabe 1 (Unendliche Listen in Haskell): a) Implementieren Sie in Haskell die Funktion odds vom Typ [Int], welche die Liste aller ungeraden natürlichen Zahlen berechnet. b) Aus der Vorlesung ist Ihnen die Funktion primes bekannt, welche die Liste aller Primzahlen berechnet. Nutzen Sie diese Funktion nun, um die Funktion primeFactors vom Typ Int -> [Int] in Haskell zu implementieren. Diese Funktion soll zu einer natürlichen Zahl ihre Primfaktorzerlegung als Liste berechnen (auf Zahlen kleiner als 1 darf sich Ihre Funktion beliebig verhalten). Z. B. soll der Aufruf primeFactors 420 die Liste [2,2,3,5,7] berechnen. Hinweise: Die vordenierten Funktionen div und mod vom Typ Int -> Int -> Int, welche die abgerundete Ganzzahldivision bzw. die modulo Operation (also den Rest bei der Ganzzahldivision) berechnen, könnten hilfreich sein. Aufgabe 2 (Unendliche Listen in Haskell): a) Geben Sie einen (2 + 2 + 3 = 7 Punkte) Haskell-Ausdruck an, der zu einer unendlichen Liste aller Palindrome ausgewertet wird. Ein Palindrom ist ein String, der vorwärts und rückwärts gelesen gleich ist. Somit ist anna ein Beispiel Strings, die aus den Zeichen 'a' bis für ein Palindrom. Wir betrachten in dieser Aufgabe ausschlieÿlich 'z' bestehen. Die berechnete Liste soll bezüglich der Länge ihrer Elemente aufsteigend sortiert sein. Sie dürfen die folgende Hilfsfunktion n strings benutzen. Diese berechnet alle Strings der Länge n, wobei das erste Argument der Funktion ist. strings strings strings where :: Int -> [ String ] 0 = [""] n = concat ( map (\ x -> map (\ tail -> x : tail ) tails ) [ 'a ' .. 'z ' ]) tails = strings (n -1) Hinweise: Die Funktion reverse :: [a] -> [a] dreht eine Liste um. 1 Programmierung WS14/15 Übungsblatt 11 (Abgabe 28.01.2015) b) Geben Sie einen Haskell-Ausdruck ausgewertet wird. Eine Zahl x≥2 an, der zu der aufsteigend sortierten Liste aller ist. Betrachten Sie als Beispiel die Zahl also ist 6 perfekten Zahlen x 1 + 2 + 3 = 6, ist genau dann perfekt, wenn die Summe ihrer echten Teiler gleich 6: Ihre echten Teiler sind 1, 2 und 3 und es gilt eine perfekte Zahl. Sie dürfen die folgende Hilfsfunktion divisors benutzen. Diese berechnet alle echten Teiler der als Argument übergebenen Zahl. divisors :: Int -> [ Int ] divisors x = filter (\ y -> mod x y == 0) [1.. div x 2] Hinweise: c) sum :: [Int] -> Int Die Funktion Geben Sie einen berechnet die Summe aller Elemente einer Liste. Haskell-Ausdruck an, der zu der aufsteigend sortierten Liste aller semiperfekten Zahlen x ≥ 2 ist genau dann semiperfekt, wenn die Summe aller oder einiger ihrer x ist. Betrachten Sie als Beispiel die Zahl 12: Ihre echten Teiler sind 1, 2, 3, 4 und 6 2 + 4 + 6 = 12, also ist 12 eine semiperfekte Zahl. ausgewertet wird. Eine Zahl echten Teiler gleich und es gilt Hinweise: Die Funktion any :: (a -> Bool) -> [a] -> Bool testet, ob ein Element einer Liste das als erstes Argument übergebene Prädikat erfüllt. Die Funktion subsequences :: [a] -> [[a]] berechnet alle Teillisten der als Argument überge- benen Liste. Es gilt zum Beispiel: subsequences [1,2,3] = [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]] subsequences Data.List lauten. Damit Sie die Funktion Lösung import nutzen können, muss die erste Zeile der Datei mit Ihrer Tutoraufgabe 3 (Programmieren in Prolog): In dieser Aufgabe sollen einige Abhängigkeiten im Übungsbetrieb Programmierung in Prolog modelliert und analysiert werden. Die gewählten Personennamen sind frei erfunden und eventuelle Übereinstimmungen mit tatsächlichen Personennamen sind purer Zufall. Person Rang J. Giesl (jgi) Professor C. Aschermann (cas) Assistent J. Hensel (jhe) Assistent F. Frohn (r) Assistent T. Ströder (tst) Assistent T. Jakobs (tja) Tutor O. Kabal (oka) Tutor F. Ail (fai) Student N. Erd (ner) Student M. Ustermann (mus) Student Schreiben Sie keine Prädikate auÿer den geforderten und nutzen Sie bei Ihrer Implementierung jeweils Prädikate aus den vorangegangenen Aufgabenteilen. a) Übertragen Sie die Informationen der Tabelle in eine Wissensbasis für für die Prädikatssymbole hatRang(X, Y), b) falls X person den Rang und Y hatRang an. Hierbei gilt Prolog. Geben Sie hierzu Fakten person(X), falls X eine Person ist und hat. Stellen Sie eine Anfrage an das im ersten Aufgabenteil erstellte Programm, mit der man herausnden kann, wer ein Assistent ist. Hinweise: 2 Programmierung WS14/15 Übungsblatt 11 (Abgabe 28.01.2015) c) Durch die wiederholte Eingabe von ; nach der ersten Antwort werden alle Antworten ausgegeben. Schreiben Sie ein Prädikat bossVon, womit Sie abfragen können, wer innerhalb der Übungsbetriebs- hierarchie einen Rang direkt über dem eines anderen bekleidet. Die Reihenfolge der Ränge ist Professor > Assistent > Tutor > Student. So ist z.B. bossVon(tja,cas) d) bossVon(cas,tja) wahr, während bossVon(tst,fai) und beide falsch sind. Stellen Sie eine Anfrage, mit der Sie alle Personen herausnden, die in der Übungsbetriebshierarchie direkte Untergebene haben. Dabei sind mehrfache Antworten mit dem gleichen Ergebnis erlaubt. e) Schreiben Sie schlieÿlich ein Prädikat vorgesetzt mit zwei Regeln, mit dem Sie alle Paare von Personen abfragen können, sodass die erste Person in der Übungsbetriebshierarchie der zweiten Person vorgesetzt ist. Eine Person X ist einer Person Y vorgesetzt, wenn der Rang von X gröÿer als der Rang von (wobei wieder Professor > Assistent > Tutor > Student gilt). So sind z.B. vorgesetzt(tst, fai) beide wahr, während vorgesetzt(tja, cas) Aufgabe 4 (Programmieren in Prolog): In dieser Aufgabe soll ein Teil der Nahrungskette in vorgesetzt(jgi, fai) Y ist und falsch ist. (2 + 1 + 1 + 1 + 2 = 7 Punkte) Prolog modelliert und analysiert werden. Die Nahrungskette besteht aus Tieren und Panzen. Bäume und Getreide sind Panzen. Elefanten, Schweine, Wölfe und Menschen sind Tiere. Elefanten essen (Teile von) Bäumen. Schweine essen Tiere und Panzen. Menschen essen Schweine und Getreide. Wölfe essen Schweine und Menschen. Schreiben Sie keine Prädikate auÿer den geforderten und nutzen Sie bei Ihrer Implementierung jeweils Prädikate aus den vorangegangenen Aufgabenteilen. Benutzen Sie a) keine vordenierten Prädikate. Übertragen Sie die oben gegebenen Informationen in eine Wissensbasis für Fakten und/oder Regeln für die Prädikatssymbole falls von b) X ein Tier ist und pflanze(X) X gegessen wird. falls X tier, pflanze Prolog. Geben Sie hierzu isst an. Hierbei gilt tier(X), gilt isst(X,Y) falls Y (teilweise) und eine Panze ist. Auÿerdem Stellen Sie eine Anfrage an das im ersten Aufgabenteil erstellte Programm, mit der man herausnden kann, wer Schweine isst. Hinweise: c) Durch die wiederholte Eingabe von ; nach der ersten Antwort werden alle Antworten ausgegeben. Schreiben Sie ein Prädikat fleischfresser, sodass fleischfresser(X) genau dann gilt, wenn X Fleisch (d.h., mindestens eine Art von Tieren) isst. Es ist nicht erlaubt, zur Lösung dieser Teilaufgabe zusätzliche Fakten anzugeben. d) Schreiben Sie ein Prädikat fressfeinde, sodass fressfeinde(X,Y) genau dann gilt, wenn X und Y Tiere sind, deren Speiseplan mindestens eine Gemeinsamkeit aufweist. Jede Tierart ist insbesondere auch Fressfeind von sich selbst. Es ist nicht erlaubt, zur Lösung dieser Teilaufgabe zusätzliche Fakten anzugeben. e) Schreiben Sie ein Prädikat nimmtZuSich, gegessen wird, oder wenn Tiere isst, die ihrerseits X sodass dieser Teilaufgabe zusätzliche Fakten anzugeben. 3 nimmtZuSich(X,Y) genau Y zu sich nehmen. Es ist dann gilt, wenn Y von X nicht erlaubt, zur Lösung Programmierung WS14/15 Übungsblatt 11 (Abgabe 28.01.2015) Tutoraufgabe 5 (Programmieren mit Listen in Prolog): In dieser Aufgabe geht es darum, Bahnhof zu verstehen. Ein Bahnhof hat eine begrenzte Anzahl n∈N von Gleisen und ein unbegrenzt langes Wartegleis. Die Idee ist, dass ein ankommender Zug sich hinten bei den wartenden Zügen einreiht. Wenn bislang kein Zug wartet, dann steht der neue Zug entsprechend vorne auf dem Wartegleis. Sobald im Bahnhof ein Gleis frei ist, fährt der Zug, der am längsten wartet, auf dieses Gleis. Auf jedem Gleis des Bahnhofs kann maximal ein Zug stehen. Auf dem Wartegleis können hingegen beliebig viele Züge stehen. Implementieren Sie in dieser Aufgabe Datenstrukturen und Prädikate, um mit solchen Bahnhöfen zu arbeiten. Benutzen Sie für Züge ein einstelliges Funktionssymbol, so dass jeder Zug eine Zahl als Wert hat. Als Beispiel stehen hier die Terme a) zug(1) und zug(2) für die Züge Zug1 und Zug2 . Verwenden Sie für Bahnhöfe ein zweistelliges Funktionssymbol bahnhof(Wartegleis, Gleise), so dass im ersten Argument das Wartegleis repräsentiert ist und das zweite Argument Informationen über die Gleise enthält. Verwenden Sie für die Terme in den beiden Argumenten jeweils die vordenierten Listen. Geben Sie freie Gleise durch die Konstante frei an, belegte Gleise durch den Term des entsprechenden Zuges. Geben Sie für die von Ihnen gewählte Darstellung der Datenstruktur die Termdarstellung eines Bahnhofs b) B an, wobei der Zug Zug3 auf dem Wartegleis steht der Bahnhof vier Gleise hat auf den Gleisen 2 und 4 die Züge Zug1 und Zug2 stehen und die anderen beiden Gleise frei sind einfuegen(Zug, GleiseVorher, GleiseNachher), das den Zug Zug auf ein GleiseVorher stellt, so dass die Gleise anschlieÿend durch GleiseNachher repräsentiert Schreiben Sie ein Prädikat freies Gleis von werden. Gehen Sie hierbei davon aus, dass GleiseVorher mindestens ein freies Gleis enthält. Ihr Prädikat sollte für Bahnhöfe mit beliebig vielen Gleisen verwendbar sein. c) Schreiben Sie ein Prädikat bewegen(bahnhof(W, G), bahnhof(WNeu, GNeu)), das wartende Züge auf freie Gleise bewegt. Hierbei ist es egal, welches freie Gleis belegt wird. In jedem Schritt soll der Zug bewegt werden, der am längsten wartet. Die Auswertung des Prädikats ist beendet, wenn kein Gleis frei ist oder kein Zug mehr wartet. Sorgen Sie dafür, dass dann in angepassten Werte von W bzw. G WNeu und GNeu die entsprechend stehen. keinPlatz(Gleise). Dieses Prädikat ist genau Gleise nirgendwo die frei-Markierung enthält. Schreiben Sie hierfür erst ein Hilfsprädikat wenn die übergebene Gleisinformation Weiterhin ist es nützlich, das bereits implementierte Prädikat Angewendet auf den obigen Beispiel-Bahnhof B einfuegen dann wahr, zu verwenden. hat der Ergebnis-Bahnhof also ein leeres Wartegleis, die Züge Zug1 und Zug2 (nach wie vor) auf den Gleisen 2 und 4 und den ehemals wartenden Zug Zug3 auf Gleis 1 oder auf Gleis 3 (wobei das andere Gleis weiterhin frei ist). Tutoraufgabe 6 (Prolog mit eigenen Datenstrukturen): Natürliche Zahlen lassen sich in Prolog (oder anderen deklarativen Sprachen) durch die Peano-Notation als Terme darstellen. Dabei stellt die Konstante X stellt s(X) die Zahl x+1 Binäre Bäume können in 0 Prolog x dargestellt durch den Term s(s(s(0))) dargestellt. werden. Sei n eine natürliche Zahl die Zahl 0 dar und für eine Zahl dar. So wird z. B. die Zahl 3 durch den Term folgendermaÿen als Terme dargestellt N. Dann repräsentiert der Term leaf(N) einen Baum mit nur einem Blatt, welches den Wert n enthält. Für zwei Bäume x und y dargestellt durch die Terme X und Y repräsentiert der Term node(X,N,Y) einen binären Baum mit einem Wurzelknoten, der den Wert n enthält und die Teilbäume x und y hat. Als Beispiel ist nachfolgend ein binärer Baum und seine Darstellung als Term angegeben. dargestellt durch den Term 4 Programmierung WS14/15 Übungsblatt 11 (Abgabe 28.01.2015) 2 1 0 1 3 node(leaf(s(0)),s(s(0)),node(leaf(s(0)),0,leaf(s(s(s(0)))))) a) b) Schreiben Sie ein Prädikat Z natürliche Zahlen x, y add/3 in Prolog, wobei add(X,Y,Z) genau dann wahr sein soll, wenn X, Y und z in Peano-Notation repräsentieren und x + y = z gilt. und isSymmetric/1 in Prolog, wobei isSymmetric(X) genau dann wahr sein soll, Schreiben Sie ein Prädikat wenn X einen symmetrischen binären Baum darstellt. Ein binärer Baum ist symmetrisch, wenn er nur aus einem Blatt besteht oder die beiden Teilbäume der Wurzel gespiegelt sind. Z. B. ist der folgende linke binäre Baum symmetrisch, während es der rechte nicht ist. 2 2 1 0 1 3 1 3 0 1 3 0 3 0 Aufgabe 7 (Prolog mit Listen und eigenen Datenstrukturen): (1 + 1 + 2 + 2.5 + 1 + 3.5 = 11 Punkte) Verwenden Sie in dieser Aufgabe keine vordenierten Prädikate. Nutzen Sie Prädikate, deren Implemen- tierung in früheren Teilaufgaben gefordert wurde, falls dies sinnvoll ist. a) Prolog darzustellen, ist die Verwendung eines nullstelligen Funktionssymbols Eine Möglichkeit, Listen in nil zur Repräsentation der leeren Liste und eines zweistelligen Funktionssymbols tion nicht-leerer Listen, wobei das erste Argument von cons zur Repräsenta- cons die Restliste ist. Auf diese Art cons(1, cons(2, cons(3, nil))) dargestellt cherte Wert und das zweite Argument von und Weise kann z.B. die Liste werden. [1,2,3] durch den Term userDefinedList(X) das genau cons beschriebene Liste ist. Implementieren Sie ein Prädikat der Funktionssymbole b) cons der in dem aktuellen Listenelement gespei- nil und Implementieren Sie ein Prädikat X asPrologList(X,Y) eine mit Hilfe der Funktionssymbole nil und dann wahr ist, wenn X eine mit Hilfe das genau dann wahr ist, wenn cons (siehe vorheriger Aufgabenteil) beschriebene Liste ist und Y die gleiche Liste wie Es soll also beispielsweise c) X beschreibt, dazu jedoch die vordenierten asPrologList(cons(1, cons(2, cons(3, nil))), [1,2,3]) Implementieren Sie ein Prädikat wenn man die Listen X und Y append(X,Y,Z) Implementieren Sie ein Prädikat X gelten. das genau dann wahr ist, wenn die Liste Z entsteht, konkateniert. Verwenden Sie zum Lösen dieser Aufgabe die vordenierten Prolog-Listen. Es soll also beispielsweise append([1,2], d) Prolog-Listen nutzt. flatten(X,Y) [2,3], [1,2,2,3]) gelten. das genau dann wahr ist, wenn eine Liste von Listen ist und 5 Programmierung WS14/15 Übungsblatt 11 (Abgabe 28.01.2015) Y jene Liste ist, die entsteht, wenn man alle Element von Es soll also beispielsweise e) X konkateniert. flatten([[1,2,3],[],[3,4]], [1,2,3,3,4]) Entwerfen Sie eine Datenstruktur, mit deren Hilfe sich Mehrwegbäume in Mehrwegbaum ist ein Baum, dessen Knoten beliebig viele Kindknoten gelten. Prolog darstellen lassen. Ein haben können. Darüber hinaus muss jeder Knoten einen beliebigen Wert speichern können. Beschreiben Sie kurz die Bedeutung der von Ihnen zu diesem Zweck verwendeten Funktionssymbole und ihrer Argumente. f) Implementieren Sie ein Prädikat X flattenTree(X,Y) das genau dann wahr ist, wenn ein Baum von Listen ist, wobei die von Ihnen im letzten Aufgabenteil entworfene Datenstruktur zur Repräsentation von Bäumen und die vordenierten Y eine Liste ist, die entsteht, indem alle in Die Reihenfolge, in der die Listen aus jene Liste, die in der Wurzel von X X X Prolog-Listen verwendet werden, und enthaltenen Listen konkateniert werden. konkateniert werden sollen, ist wie folgt: Am Anfang steht gespeichert ist. Es folgen alle Listen, die in dem durch den ersten Kindknoten denierten Teilbaum gespeichert sind, gefolgt von allen Listen, die in dem durch den zweiten Kindknoten denierten Teilbaum gespeichert sind, usw. Es gilt also beispielsweise [1,2,3,15,7,3,7,15,11,12]), wenn X der folgende Mehrwegbaum ist: [1,2,3] [] [15] [] [7,3] [7,15] [11,12] 6 flattenTree(X,