P1-WS04-MusterLoesung06.txt
Version vom 1. Dezember 2006, 19:13 Uhr von Muelli (Diskussion | Beiträge)
% Musterloesung Aufgabenblatt 6 % P1 WiSe 04/05 % Daniel Schreckling % Aufgabe 1 % --------- % Hilfsprädikat max(+Zahl1, +Zahl2, ?Max) % % Liefert in ?Max das Maximum der Zahlen +Zahl1 % und +Zahl2 max(Zahl1, Zahl2, Zahl2) :- Zahl1 < Zahl2. max(Zahl1, Zahl2, Zahl1) :- Zahl1 >= Zahl2. % Hilfsprädikat Ort(?Ort, ?Hoehe) % % Liefert die ?Hoehe zu einem Ort ?Ort ort(Ort, Hoehe) :- region(Ort,Hoehe). ort(Ort, Hoehe) :- wasserwerk(Ort, Hoehe). ort(Ort, Hoehe) :- pumpstation(Ort, Hoehe). % es werden Prädikate aus früheren Übungsaufgaben verwendet % und modifiziert % Aufgabe 1a % ---------- % Hilfsprädikat hoehen_unterschied(+Ort1, +Ort2, ?Unterschied) % % berechnet die Hoehendifferenz nach der Vorschrift: % Hoehe von Ort1 minus Hoehe von Ort2 hoehen_unterschied(Ort1, Ort2, Unterschied) :- ort(Ort1, Hoehe1), ort(Ort2, Hoehe2), Unterschied is (Hoehe1 - Hoehe2). % hoehen_unterschied_verb(+Senke, +Quelle, ?Unterschied) % % Gelingt, wenn +Senke und +Quelle in Fließrichtung direkt % miteinander verbunden sind. ?Unterschied enthält bei % Erfolg den Hoehenunterschieds ziwschen Senke und Quelle hoehen_unterschied_verb(Senke, Quelle, Unterschied) :- ist_angeschlossen_an(Senke, Quelle), hoehen_unterschied(Senke, Quelle, Unterschied). % Aufgabe 1b % ---------- % hoehenunterschied_ww_verbr(+Wasserwerk, +VerbrRegion, ?Unterschied) % % Gelingt, wenn die Verbraucherregion +VerbrRegion letztlich von % +Wasserwerk mit Wasser versorgt wird. ?Unterschied enthaelt bei Erfolg % den Hoehenunterschied zwischen Wasserwerk und Verbraucherregion. % Da es mehrere Wege geben kann, liefert hoehen_unterschied_ww_verbr\3 % gegebenenfalls auch mehrer Hoehenunterschiede. hoehenunterschied_ww_verbr(Wasserwerk, VerbrRegion, Unterschied) :- wasserwerk(Wasserwerk, HoeheWW), region(VerbrRegion, HoeheVR), wird_versorgt_von(VerbrRegion, Wasserwerk, _), hoehen_unterschied(VerbrRegion, Wasserwerk, Unterschied). % Aufgabe 1c % ---------- % wird_versorgt_von(?Senke, ?Quelle, ?MaxDiff) % % Gelingt, wenn ?Senke von ?Quelle mit Trinkwasser versorgt wird. % In ?MaxDiff wird die größte Höhendifferenz gespeichert, % die auf irgendeinem Weg von der Senke zur Quelle überwunden wird. % Da es mehrere Wege geben kann, liefert wird_versorgt_von\2 % gegebenenfalls auch mehrer Hoehenunterschiede. wird_versorgt_von(Senke,Quelle, MaxDiff) :- wasserwerk(Quelle, _), ist_angeschlossen_an(Senke,Quelle), hoehen_unterschied(Senke, Quelle, MaxDiff). wird_versorgt_von(Senke,Quelle, MaxDiff) :- ist_angeschlossen_an(Senke,Ort), wird_versorgt_von(Ort,Quelle, ThisDiff), hoehen_unterschied(Senke, Ort, Diff), max(Diff, ThisDiff, MaxDiff). % max_hoehenunterschied_ww_verbr(+Wasserwerk, +VerbrRegion, ?MaxDiff) % % Gelingt, wenn die Verbraucherregion +VerbrRegion letztlich von % +Wasserwerk mit Wasser versorgt wird. ?MaxDiff liefert bei Erfolg % den maximalen Hoehenunterschied zwischen zwei Netzknoten auf dem Weg % zwischen Wasserwerk und Verbraucherregion. % Da es mehrere Wege geben kann, liefert hoehen_unterschied_ww_verbr\3 % gegebenenfalls auch mehrer Hoehenunterschiede. max_hoehenunterschied_ww_verbr(Wasserwerk, VerbrRegion, MaxDiff) :- region(VerbrRegion, _), wasserwerk(Wasserwerk, _), wird_versorgt_von(VerbrRegion, Wasserwerk, MaxDiff). % Aufgabe 2a % ---------- % zinseszins(+Anlage,+Zinssatz,+Laufzeit,?Ausschuettung) % % Das Kapital +Anlage ist in Währungseinheiten anzugeben, % der +Zinssatz in Prozent, z.b. `5' entspricht 5%, % die +Laufzeit in Jahren. % Die +Ausschuettung wird ebenfalls in Währungseinheiten ausgegeben zzins(Anlage, _, 0, Anlage). zzins(Anlage, Zinssatz, Laufzeit, Ausschuettung) :- Laufzeit > 0, Years2Go is Laufzeit - 1, zzins(Anlage, Zinssatz, Years2Go, ZwischenBetrag), Ausschuettung is (ZwischenBetrag * (1 + Zinssatz/100)). % Aufgabe 2b % ---------- % Im Prolog-System genügen fünf Nachkommastellen, um genaue % Verdopplung zu erreichen: % % ?- zzins(1000,7.17735,10,X). % % X = 2000.0 % Es gibt eine analytische Loesung, denn für das Kapital % K_n nach n Jahren gilt bei einem Zinssatz p und einem % Startkapital K: % % K_n = K * (1 + p/100)^n % % Damit ergibt sich für eine Verdopplung von K nach 10 Jahren % (also K_10 = 2 * K) für den Zinssatz p folgende Gleichheit: % % p = (sqrt(10, 2) - 1) * 100 = 7.1773463 % % wobei sqrt(10, 2) die 10te Wurzel aus 2 berechnet. % Aufgabe 2c % ---------- % Prädikat zzinslist(+Anlage, +Zinssatz, +Laufzeit, ?Liste) % % Liefert zu einem Startkapital +Anlage und einem Zinssatz +Zinssatz % eine Liste ?Liste der Kapitalbeträge in den Jahren +Laufzeit, in % denen das Anlagekapital verzinst wird zzinslist(Anlage, Zinssatz, Laufzeit, Liste) :- findall( kapital(Jahr, Kapital), (between(0, Laufzeit, Jahr), zzins(Anlage, Zinssatz, Jahr, Kapital)), Liste). % ?-zzinslist(10000, 7.17735, 10, List). % List = [kapital(0, 10000), % kapital(1, 10717.7), % kapital(2, 11487.0), % kapital(3, 12311.4), % kapital(4, 13195.1), % kapital(5, 14142.1), % kapital(6, 15157.2), % kapital(7, 16245.1), % kapital(8, 17411.0), % kapital(9, 18660.7), % kapital(10, 20000.0)] % Aufgabe 3 % --------- % Hier ein Beispiel, in dem das Ausmaß des quadratischen Wachstums % veranschaulicht wird. Es wird eine normale Parabel gezeichnet, deren % Punkte aber proportional zum Funktionswert größer werden. Das % Ergebnis könnte jedem Monster/Alien/Katastrophenfilm entnommen sein; % schon kubisches Wachstum wäre nicht mehr richtig zu erkennen, % geschweige denn exponentielles. % % Man beachte die symmetrischen Moirémuster unterhalb des letzten % Funktionswertes. draw(Max) :- free(@bild), new(@bild,picture('Beispiel',size(900,900))), send(@bild,background,colour(black)), send(@bild,open), draw_parabola(@bild,0,Max). % draw_parabola(+Bildobjekt, +X, +MaxX) erzeugt eine normale Parabel, % d.h. die Kurve y = x^2, wobei die Punkte proportional zum Wert y % größer werden. draw_parabola(_,X,MaxX):- X >= MaxX. draw_parabola(Bild,X,MaxX) :- Y is X*X / 100, new(O, circle(Y)), send(O,fill_pattern(colour(yellow))), % XPCE zählt Y von links oben, aber wir wollen von links unten zählen Y2 is 300 - Y, send(Bild, display(O, point(X,Y2))), X2 is X + 1, draw_parabola(Bild,X2,MaxX). % :-draw(300). % Aufgabe 4a % ---------- % (i) Bindungen sind X=y und Y=x % (ii) Bindungen sind L=a und X=[a,a] % (iii) Bindungen sind F=[a,b], G=[[a,[b]], [[b]|a]], A=a und B=[b] % Aufgabe 4b % ---------- %% Prädikat last\2 %% mylast(+List, +Element) %% Ausgabe: yes, wenn letztes Element der Liste +List %% mit dem Element +Element identisch ist. mylast([Last], Last). mylast([_|Tail], Element) :- mylast(Tail, Element). % Das Prädikat läßt sich sowohl zum Testen als auch zum Extrahieren % oder Generieren einsetzten. Wenn nur Variable angegeben werden, % werden nacheinander abstrakte Listen aller möglichen Längen % angegeben. Bei leeren Listen mißlingt der Aufruf sofort. % Aufgabe 4c % ---------- % Hilfsprädikat gerade_Pos(+Liste, ?Element) % ist erfolgreich, falls ?Element an einer Position % in +Liste mit geradem Index steht (der Index ist % nullbasiert, d.h. das erste Element in der Liste hat % Index 0, das zweite Element den Index 1, ...) % % Die Anwendung dieses Prädikates auf eine leere Liste % ist nicht erfolgreich. gerade_Pos([_,E|_], E). gerade_Pos([_,_|R], E) :- gerade_Pos(R,E). % Teil (i) % -------- % Prädikat slice_i(+Liste, ?NewList) % % Extrahiert aus der Liste +Liste jedes zweite Element und % speichert diese mit Hilfe gerade_Pos/2 und findall/3 in % ?NewList % % Da gerade_Pos/2 für eine leere Liste nicht erfolgreich, % liefert slice_i([], NewList) in NewList auch eine leere % Liste. slice_i(List, NewList) :- findall(Element, gerade_Pos(List, Element), NewList). % Teil (ii) % --------- % Prädikat slice_ii(+Liste, ?NewList) % % Extrahiert aus der Liste +Liste jedes zweite Element und % konstruiert mit Hilfe von von Rekursion eine Ergebnisliste, % die genau diese Elemente enthält slice_ii([], []). slice_ii([_], []). slice_ii([_,Element2|Tail], [Element2|NewList]) :- slice_ii(Tail, NewList).