Aufgabe 1:

Werbung
-1-
Aufgabe 1:
(15 Punkte)
Eine Tischlerei benötigt zur Herstellung ihrer Regalserie „Freddie“ Bretter der Länge 1 bzw.
2 Meter, welche aus längeren Brettern des Zulieferers zugeschnitten werden müssen. Die
Länge der Ausgangsbretter in Metern ist dabei stets ganzzahlig.
Schreiben Sie eine Java-Methode static void brettlaengen(int laenge),
welche für ein Ausgangsbrett der Länge laenge alle möglichen Zuschnittskombinationen
für Bretter der Länge 1 bzw. 2 Meter ausgibt.
Die Kombinationen für ein Ausgangsbrett der Länge 3 sind z.B.:
2 1
1 2
1 1 1
Lösung:
public static void brettlaengen(int laenge){
brettlaengen("", laenge);
}
public static void brettlaengen(String kombinationen, int laenge){
if (laenge == 0)
System.out.println(kombinationen);
if (laenge >= 1)
brettlaengen(kombinationen + " 1", laenge - 1);
if (laenge >= 2)
brettlaengen(kombinationen + " 2", laenge - 2);
}
-2-
Aufgabe 2:
(15 Punkte)
Gegeben seien die folgenden Haskell-Funktionsdefinitionen:
mult2 :: Int -> Int
mult2 a = a + a
g :: (Int -> Int) -> Int -> Int
g f x = f (x * x)
Reduzieren Sie den Ausdruck g mult2 2 + g (+ 1) 2 schrittweise! Wenden Sie dabei
in jedem Schritt nur eine Reduktionsregel an und dokumentieren sie die jeweiligen Zwischenschritte! In einigen Schritten kommen mehrere Redexe für eine Reduktion in Frage. Gehen
Sie in diesen Fällen davon aus, dass der am weitesten links stehende, äußerste Redex zuerst
reduziert wird. Beachten Sie, dass Teilausdrücke ggf. mehrfach ausgewertet werden müssen!
Lösung:
g mult2 2 + g (+1) 2
mult2 (2 * 2) + g (+1) 2
(2*2) + (2*2) + g (+1) 2
4 + (2*2) + g (+1) 2
4 + 4 + g (+1) 2
8 + g (+1) 2
8 + (+1) (2 * 2)
8 + (+1) 4
8 + 5
13
-3-
Aufgabe 3:
(15 Punkte)
Entwickeln Sie in einer Programmiersprache Ihrer Wahl (Haskell oder Java) eine Funktion
bzw. Methode, welche alle möglichen Permutationen einer ihr übergebenen Liste paarweise
disjunkter, natürlicher Zahlen erzeugt.
Die Liste der Permutationen der Liste [1, 2, 3] wäre z.B.:
[[1, 2, 3], [1, 3, 2],
[2, 1, 3], [2, 3, 1],
[3, 1, 2], [3, 2, 1]]
Hinweis: Für eine Implementierung in Java bietet sich die Verwendung von Arrays anstelle
von Listen an.
Haskell-Lösung:
-- man erzeugt alle permutationen einer liste (l:ls), indem man alle
-- Permutationen der liste ls erzeugt und l an allen Positionen dieser
-- Permutationen einmal einfügt.
perm :: [a] -> [[a]]
perm [] = [[]]
perm (l:ls) = insert l (perm ls)
-- fügt ein Element in alle Positionen einer Liste von Listen ein
insert :: a -> [[a]] -> [[a]]
insert x [] = []
insert x (y:ys) = (map (insert2 x y) [0 .. (length y)]) ++ insert x ys
-- fügt
insert2
insert2
insert2
insert2
ein Element an eine bestimmte Stelle einer Liste ein
:: a -> [a] -> Int -> [a]
a [] n = [a]
a (y:ys) 0 = (a:(y:ys))
a (y:ys) n = (y:(insert2 a ys (n-1)))
oder etwas kürzer:
perm :: [a] -> [[a]]
perm [] = [[]]
perm (x:xs) = [ps ++ [x] ++ qs | rs <- perm xs,
(ps, qs) <- splits rs]
splits :: [a] -> [([a],[a])]
splits [] = [([], [])]
splits (y:ys) = ([],y:ys):[(y:ps,qs) | (ps,qs) <- splits ys]
-4-
Java-Lösung:
public static int[][] permutation(int[] liste){
// die erste Permutation im Ergebnis ist die liste selbst
int[][] result = new int[1][liste.length];
result[0] = liste;
// der rest entsteht durch Vertauschung. Dabei wird jedes Element der
// Liste mit jedem der weiter rechts in der Liste stehenden Elementen
// einmal vertauscht.
for (int left = 0; left < liste.length - 1; left++){
// wie viele Permutation gibt es bereits, aus denen durch
// Vertauschungen neue Permutationen entstehen?
int anz = result.length;
// in den bisherigen Perumtationen das Element an Position left mit
// allen rechts danebenliegenden vertauschen und die neuen
// Permutationen hinten anhängen
for (int right = left + 1; right < liste.length; right++){
for (int zeile = 0; zeile < anz; zeile++){
// die neue Permutation erzeugen
int[] newperm = new int[liste.length];
// Reihenfolge aus der alten Permutation übernehmen
for (int h = 0; h < newperm.length; h++)
newperm[h] = result[zeile][h];
// Elemente left und right vertauschen
newperm[left] = result[zeile][right];
newperm[right] = result[zeile][left];
// neue Permutation anhängen
result = append(result, newperm);
}
}
}
return result;
}
static int[][] append(int[][] r, int[] a){
int[][] result = new int[r.length + 1][];
for (int i = 0; i < result.length - 1; i++)
result[i] = r[i];
result[result.length - 1] = a;
return result;
}
-5-
Aufgabe 4:
(6+10+8 = 24 Punkte)
Eine Versicherungsagentur beschließt im Rahmen eines Forschungsprojektes die Realisierung
einiger Teile ihrer Mitarbeiter-, Kunden- und Policenverwaltung durch eine neue, in Java zu
implementierende Software zu erproben. Kernkomponenten dieser neuen Software bilden die
Klassen Mitarbeiter, Kunde und Police, welche durch eine möglichst genaue Abbildung der in
der Realität auftretenden Abhängigkeiten miteinander verknüpft werden sollen. Das Projektteam hat hierfür folgende Abhängigkeiten analysiert:
Die Agentur beschäftigt mehrere Mitarbeiter, welche jeweils wiederum für unterschiedliche
Kunden zuständig sind. Um ein persönliches Verhältnis zu den Kunden aufbauen zu können,
wird jeder Kunde nur von einem Mitarbeiter betreut. Da die Agentur verschiedene Arten von
Versicherungen anbietet, kann jeder Kunde mehrere Versicherungspolicen besitzen. Die
Provision, welche die Agentur durch die Vermittlung der Versicherungspolice erhalten hat,
wird in den Policen selbst festgehalten.
Für die erste Version der Software wurden für die einzelnen Klassen folgende Methoden
definiert:
Klasse Police:
• double getProvision()
• String getPolicenID()
// gibt die Provision der Police aus
// gibt das Aktenzeichen der Police aus
Klasse Kunde:
• void addPolice(Police police) // fügt eine neue Police zu den Policen des
// Kunden hinzu
• String getName()
// gibt den Namen des Kunden zurück
• String getAnschrift()
// gibt die Anschrift des Kunden zurück
• Police[] getPolicen()
// gibt ein Array aller Policen den Kunden
// zurück
Klasse Mitarbeiter:
• void addKunde(Kunde kunde)
•
•
String getName()
Enumeration getKunden()
•
void provisionenAusgeben()
// fügt einen neuen Kunden in die Liste der
// Kunden des Mitarbeiters ein
// gibt den Namen des Mitarbeiters aus
// Gibt eine Aufzählung aller Kunden des
// Mitarbeiters aus
// Erzeugt eine Liste der Provisionssummen
// pro Kunde des Mitarbeiters
a) Stellen Sie die im Text geschilderte Situation durch ein Klassendiagramm dar!
b) Implementieren Sie die Klassen Police und Kunde. Achten Sie dabei besonders auf
sinnvolle Parameter für die jeweiligen Konstruktoren und eine sichere Kapselung der zu
verwaltenden Daten.
c) Schreiben Sie die Methode provisionenAusgeben() der Klasse Mitarbeiter, welche
eine Auflistung aller Kunden und die Summen der durch Verträge mit ihnen erwirtschafteten Provisionen ausgibt!
Hinweis: 1. Die übrigen Methoden der Klasse Mitarbeiter brauchen in dieser Aufgabe
nicht implementiert zu werden.
2. Die einzigen Methoden des Interface Enumeration sind: Object nextElement()
und boolean hasMoreElements()
-6-
a)
*
Kunde
name:String
anschrift:String
policen:Police[]
addPolice(police:Police)
getName()String
getAnschrift():String
getPolicen():Police[]
1
Mi tarbeiter
name:String
1 kund en:Vect or
addKunde(kun de:Kunde)
getName():String
getKun den():Enumera tion
provi sionenAusgeben()
Police
provi sion:doub le
id:String
* getProvision ():double
getPolicenID():double
b)
public class Police {
protected double provision;
protected String id;
public Police (String id, double provision){
this.id = id;
this.provision = provision;
}
public double getProvision(){
return provision;
}
public String getID(){
return id;
}
}
-7-
public class Kunde {
protected String name;
protected String anschrift;
protected Police[] policen;
public Kunde(String name, String anschrift){
this.name = name;
this.anschrift = anschrift;
this.policen = new Policen[0];
}
public String getName(){
return name;
}
public String getAnschrift(){
return anschrift;
}
public void addPolice(Police police){
Police[] tmp = policen;
policen = new Police[tmp.length + 1];
for (int i = 0; i < tmp.length; i++)
policen[i] = tmp[i];
policen[policen.length – 1] = police;
}
public Police[] getPolicen(){
return policen;
}
}
c)
public static void provisionenAusgeben(){
Enumeration kunden = getKunden();
while (kunden.hasMoreElements()){
Kunde kunde = (Kunde)kunden.nextElement();
double provision = 0;
Police[] policen = kunde.getPolicen();
for (int i = 0; i < policen.length; i++)
provision += policen[i].getProvision();
System.out.println(kunde.getName() + ": " +
provision);
}
}
-8-
Aufgabe 5:
(10 Punkte)
Gegeben sei die folgende Java-Klasse:
public class Preis{
public double p;
* Name nicht Aussagekräftig
private Preis(double p){
p = p;
}
* Konstruktor ist private
* this. fehlt
protected static int bruttoPreis{
* static, * int statt double,
* Klammer vergessen
* Konstanten sollten als solche
definiert werden
return p + p * 0.16;
}
public void reduzieren(double p){
* throws … vergessen
if (p < 0) throw new InvalidArgumentException();
this.p = this.p * (1 - p);
}
}
public static double sum(Preis[] a){
int i = 1;
* Arrayindex startet bei 0
double r;
* Variable nicht initialisiert
while (i < a.length()){
* Klammern zuviel
r = r + a[i];
* a[i] ist kein double sondern
ein Objekt. Es fehlt das .p
* Schleifenzähler wird nicht erhöht
}
return r;
}
Unterstreichen Sie die in dem Quellcode vorhandenen Fehler und dokumentieren Sie die Art
des Fehlers in kurzen Stichpunkten.
-9-
Aufgabe 6:
(24 Punkte)
Gegeben sei das IMP-Programm P:
while n > 0 do (e := e * 2; n := n – 1)
Ermitteln Sie die Reduktionssemantik von P in der Umgebung ρ und im Zustand σ, wobei
σ (α1 ) = 1
gilt: ρ (n ) = α1
ρ (e) = α 2
σ (α 2 ) = 1
Lösung:
Lemma1:
e, ρ , σ → 1 2, ρ , σ → 2 n, ρ , σ [α 2 / 2] → 1 1, ρ , σ [α 2 / 2] → 1
e * 2, ρ , σ → 2
n − 1, ρ , σ [α 2 / 2] → 0
e := e * 2, ρ , σ → σ [α 2 / 2] n := n − 1, ρ , σ [α 2 / 2] → σ [α1 / 0, α 2 / 2]
e := e * 2; n := n − 1, ρ , σ → σ [α1 / 0, α 2 / 2]
Lemma2:
n, ρ , σ [α1 / 0, α 2 / 2] → 0 0, ρ , σ [α1 / 0, α 2 / 2] → 0
n > 0, ρ , σ [α1 / 0, α 2 / 2] → false
while n > 0 do (e := e * 2; n := n − 1), ρ , σ [α1 / 0, α 2 / 2] → σ [α1 / 0, α 2 / 2]
Hauptrechnung:
n, ρ , σ → 1 0, ρ , σ → 0
Lemma1 Lemma 2
n > 0, ρ , σ → true
while n > 0 do (e := e * 2; n := n − 1), ρ , σ → σ [α1 / 0, α 2 / 2]
Herunterladen