P1-WS04-MusterLoesung06.txt

Aus Fachschaft_Informatik
Zur Navigation springen Zur Suche springen
%						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]]).