Klausur - iLearn - Christian-Albrechts

Werbung
Christian-Albrechts-Universität zu Kiel
Institut für Informatik
Lehrstuhl für Programmiersprachen und Übersetzerkonstruktion
Prof. Dr. Michael Hanus, Sandra Dylus, Björn Peemöller
1. Klausur zur Vorlesung „Fortgeschrittene Programmierung“
SS 15
Hinweis: Sie können Statistiken zur Klausur einsehen.
Diese Klausur besteht aus 6 Aufgaben auf 5 doppelseitig bedruckten Blättern.
Gesamtpunktzahl: 65 Punkte, Punktzahl zum Bestehen: 32 Punkte.
Einlesezeit: 15 Minuten, Bearbeitungszeit: 120 Minuten.
Bitte schreiben Sie auf jedes Blatt, das Sie abgeben, Ihren Namen und Ihre Matrikelnummer!
Alle Aufgaben können unabhängig voneinander bearbeitet werden, insbesondere auch einzelne Aufgabenteile.
Hierbei können Definitionen aus vorherigen Aufgabenteilen verwendet werden, auch wenn diese nicht gelöst
wurden.
Aus der Vorlesung bekannte Konstrukte (Prelude von Haskell, Prolog-Prädikate) dürfen verwendet werden.
Hinweis: Die Einsichtnahme in die korrigierten Klausuren findet voraussichtlich am 26.08.2015 (Mittwoch),
gestaffelt von 11:00 bis 11:30 Uhr (Nachnamen A-J) und von 11:30 bis 12:00 Uhr (K-Z) im CAP4 (Hochhaus)
Raum 715, statt. Bitte bringen Sie dazu einen Lichtbildausweis mit.
Viel Erfolg!
1
Aufgabe 1 - FortProg ist: [ ] objekt-orientiert; [ ] funktional; [ ] logisch; [ ] manchmal nicht auszuhalten
15 Punkte
Es könnte/n alle, mehrere, eine oder gar keine Antwort richtig sein. Schreiben Sie die jeweiligs richtigen
Antworten und ggf. zusätzliche Angaben zu jeder Frage auf; sollte keine der Antwortmöglichkeiten zutreffen,
formulieren Sie dies bitte explizit. Markierungen auf dem Aufgabenzettel werden nicht berücksichtigt!
Java
1. Welche der folgenden Generic-Konstrukte beschreiben Bounded Wildcards?
a)
b)
c)
d)
e)
<?
<C
<?
<A
<?
extends B>
super ?>
instance A>
extends ?>
super A>
2. Threads in Java - welches der Programme ist valide (Hinweis: es handelt sich dabei in keinem Fall um
Syntaxfehler)?
a) public class MyThread implements Runnable {
@Override
public void run() {
}
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
myThread.start();
}
}
b) public class MyThread implements Runnable {
@Override
public void run() {
}
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new Thread(new MyThread());
myThread.start();
}
}
c) public class MyThread extends Thread {
@Override
public void run() {
}
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
myThread.start();
}
}
d) public class MyThread extends Thread {
@Override
public void run() {
}
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new Thread(new MyThread());
2
myThread.start();
}
}
3. Welcher Thread wacht beim Aufruf von notify() auf?
a)
b)
c)
d)
e)
Es wacht immer der zuletzt schlafengelegte Thread auf.
Mittels der Übergabe der Thread-ID kann ein bestimmter Thread geweckt werden.
Es wachen alle Threads auf und bewerben sich neu um das Lock.
Es wacht immer der zuerst schlafengelegte Thread auf.
Es wird ein beliebiger der systemweiten schlafenden Threads geweckt.
4. Welche der Aussagen bzgl. reentrent und Synchronisationsverfahren sind wahr?
a)
b)
c)
d)
e)
Eingebaute Locks (synchronized-Blöcke) sind reentrent.
Semaphoren sind reentrent.
Threads sind bereits reentrent.
Binäre Semaphoren sind reentrent, andere Semaphoren sind es jedoch nicht.
Eingebaute Locks sind nur auf this reentrent.
5. Welche der Aussagen gelten für RMI in Java bei verteilten Methodenaufrufen?
a)
b)
c)
d)
e)
Bei Remote-Objekten wird nur eine Referenz des Objektes übertragen.
Serializable-Objekte werden in Bytes umgewandelt.
Primitive Werte werden nicht kopiert.
Die Parameter und der Rückgabewert müssen nicht in Bytes umgewandelt werden.
Die Netzwerkkommunikation über TCP/IP ist für den Anwendungsprogrammierer sichtbar.
Prolog
5. Welche der folgenden Zeichenfolgen sind syntaktisch korrekte Objekte in Prolog? Geben Sie für jede der
Antwortmöglichkeiten die Kategorie (Atom, Variable, Struktur) oder kein zulässiges Objekt an.
a)
b)
c)
d)
e)
xY
++
_x
F([1,a,3])
likes(john,mary)
6. Welche der folgenden Zeichenfolge sind valide Listen in Prolog?
a)
b)
c)
d)
e)
[1,2 | [3]]
[1 | 3]
[[1] | [3]]
[1, atom | []]
[1,2]
7. Welche der Anfragen wird mit true beantwortet?
a)
b)
c)
d)
e)
?????-
42 is 7 * 6.
1 + 7 is 1 + 7.
1 + 3 is 5 - 1.
3 * 4.
1 * 7 is 7.
8. Welche der Anfragen wird einer Variablenbindung beantwortet? Sollten Bindungen berechnet werden,
notieren Sie diese hinter der jeweiligen Zeile.
3
a)
b)
c)
d)
e)
?????-
X
X
Y
Z
3
= 2, Y
is 5 +
is 3 +
is 3 +
+ 7 is
is 5 + X.
3 * 2.
X, X = 2.
Y.
X.
9. Welche Aussagen über Prolog sind richtig?
a) Die Auswertungsstrategie basiert auf Breitensuche.
b) Prolog ist eine Obermenge der Prädikatenlogik 1. Stufe.
c) σ heißt allgemeinster Unifikator, falls für alle Unifikatoren σ 0 eine Substitution φ existiert mit
σ = φ · σ0 .
d) Variablen werden groß geschrieben.
e) Die Implementierung von Funktionen ist in Prolog in Form von Relationen möglich.
Haskell
11. Der Ausdruck [("Hallo",True),("Welt",False)] hat den folgenden Typ:
a)
b)
c)
d)
e)
[String]
[(String,Bool)]
(a,Bool)
[String,Bool]
[(String,Bool),(String,Bool)]
12. Welcher der folgenden Ausdrücke enthält einen Typfehler:
a)
b)
c)
d)
e)
1 : 2 : [3,4]
[(1),(2)] ++ [()]
[1,2,3] ++ 4
[[1,2]] ++ [[3,4]]
1 : 2 : 3 : 4 : []
13. Die Berechung des Ausdrucks [(x,y) | y <- [1..3], x <- [1..2]] ergibt:
a)
b)
c)
d)
e)
[(1,1),(1,2),(1,3),(2,1),(2,2),(2,3)]
[(1,1),(1,2),(2,1),(2,2),(3,1),(3,2)]
[(1,2),(2,1),(3,2),(1,1),(2,2),(3,1)]
[(1,1),(2,1),(1,2),(2,2),(1,3),(2,3)]
[(1,1),(2,1),(3,1),(1,2),(2,2),(3,2)]
14. Die Funktion twice f x = f (f x) hat den folgenden Typ:
a)
b)
c)
d)
e)
a -> a -> a
(a -> a) -> a -> a
a -> (a -> a) -> a
a -> a -> (a -> a)
a -> a -> a -> a
15. Bezüglich des Datentyps data Tree a b = Tip a | Branch (Tree a b) b (Tree a b) sind folgende
Werte korrekt:
a) Tip (Branch (Tip 2) (Tip True) (Tip 4))
b) Branch (Tip (1)) 2 (Tip ())
c) Tip (Branch (Tip 1) "Hallo" (Tip 2))
4
d) Branch (Tip "Hallo") () (Tip "Welt"))
e) Tip ()
Aufgabe 2 - Wie sah nochmal die richtige Lösung aus?
10 Punkte
Oh nein, beim Erstellen der Musterlösung ist leider eine studentische Lösung (vom Vorjahr) anstelle der
korrekten Lösung in die Zwischenablage (copy+paste sei Dank!) geraten. Bei der Aufgabe handelt sich um
die verbesserte Version des Buffer1 mit Synchronisationsobjekten, die wir um zusätzliche Funktionalitäten
erweitert haben. Die bereits vorgegebenen Methoden sind in dieser Abgabe gar nicht vorhanden, sondern nur
die neu definierten Methoden.
Bei der Korrektur wurden die folgenden Fehler gefunden:
• if-Anweisung falsch! -1
• r/w vertauscht! -1
• Verwendung von wait/notify! -1
Geben Sie für jeden der drei Fehler die entsprechende Zeile, die Begründung sowie eine entsprechende Korrektur
an.
1
import java.util.concurrent.TimeoutException;
2
3
4
5
6
7
8
9
/**
* Single element buffer with synchronization.
*
* @param <E>
*
Type of the element
*/
public class ExtBuffer<E> {
10
11
12
13
// element + empty flag
private E content;
private boolean empty;
14
15
16
17
// synchronization objects
private Object r = new Object();
private Object w = new Object();
18
19
20
21
public ExtBuffer() {
empty = true;
}
22
23
24
25
26
public ExtBuffer(E content) {
this.content = content;
empty = false;
}
27
28
29
30
31
32
33
34
35
/**
* Try to put an element into the buffer; succeeds only for an empty buffer
*
* @param elem
*
Element to put into
* @return true if successful
*/
public boolean tryPut(E elem) {
5
synchronized (w) {
if (empty) {
synchronized (r) {
content = elem;
empty = false;
r.notify();
return true;
}
} else {
return false;
}
}
36
37
38
39
40
41
42
43
44
45
46
47
}
48
49
/**
* Swap the element in the buffer with the given element. Suspends if the
* buffer is empty.
*
* @param elem
*
Element to swap with
*/
public E swap(E elem) throws InterruptedException {
synchronized (r) {
if (empty) {
r.wait();
}
synchronized (w) {
E res = content;
content = elem;
w.notify();
return res;
}
}
}
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
* Overwrite the element in the buffer, even if the buffer is empty
*
* @param elem
*
Element to overwrite with
*/
public void overwrite(E elem) {
synchronized (r) {
content = elem;
if (empty) {
synchronized (w) {
empty = false;
r.notify();
}
}
}
}
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
}
6
10 Punkte
Aufgabe 3 - Make it pretty!
In dieser Aufgabe wollen wir uns bereits vorgegebene Haskell-Definitionen anschauen und diese verbessern
bzw. in einem anderen Stil umschreiben.
1. Die zwei folgenden Funktionsdefinitionen sehen sich sehr ähnlich. Schreiben Sie beide Definitionen mit
Hilfe einer Funktion höherer Ordnung um. Sie können diese Funktion höherer Ordnung entweder selbst
definieren oder eine vordefinierte Funktion aus der Prelude verwenden.
import Data.Char (isDigit)
findEvens :: [Int] -> [Int]
findEvens [] = []
findEvens (x:xs) =
if even x
then x : findEvens xs
else findEvens xs
findDigits :: String -> String
findDigits [] = []
findDigits (x:xs) =
if isDigit x
then x : findDigits xs
else findDigits xs
2. Die folgende Funktion filtert für eine gegebene Liste von Strings genau die Strings heraus, die nur aus
Buchstaben bestehen. Für diese Strings wird dann eine Tabelle mit der korrespondierenden Anzahl der
Buchstaben ausgegeben.
import Data.Char (isAlpha)
letterTable :: [String] -> IO ()
letterTable []
= return ()
letterTable (x:xs)
| all isAlpha x = do
putStrLn (x ++ ": " ++ show (length x) ++ " letters")
letterTable xs
| otherwise
= letterTable xs
Es ist kein guter Stil, puren Code mit IO-Aktionen zu vermischen. Daher unterteilen wir diese Funktionsdefinition in zwei Teile: in einen puren Teil und einen Teil mit IO-Aktion. Implementieren Sie im
folgenden Code die noch fehlende pure Funktionalität der Originalfunktion letterTable.
letterTable :: [String] -> IO ()
letterTable strs = putStr (alphaWords strs)
-- Hier fehlt noch die entsprechende Implementierung
alphaWords = undefined
3. In der Eile kann es schon mal passieren, dass man vergisst, Typsignaturen für selbstdefinierte Funktionen
anzugeben. Schreiben Sie die (möglichst allgemeinen!) Typsignaturen für die jeweiligen Funktionen auf.
Wenn die Funktionen noch einen sinnvollen Namen hätten, wäre die Aufgabe vemutlich noch einfacher
gewesen; geben Sie den Funktionen im Anschluss noch einen sinnvollen Namen!
fa [] _ = []
fa (x:xs) p = (x,p) : fa xs p
7
fb a b c d = if a then d b else d c
fc x = fc x
fd [] g z = z
fd (x:xs) g z = g x (fd xs g z)
fe x [] = False
fe x (y:ys) = x == y || fe x ys
10 Punkte
Aufgabe 4 - 101010
In dieser Aufgabe sollen Sie sich mit der allseits beliebten Binärzahlkodierung beschäftigen. Erinnern Sie sich
noch an die definierten Funktoren in Prolog aus Übungsblatt 10 Aufgabe 3? Wenn nein, bekommen Sie bitte
keine Panik, es folgt eine kleine Gedächtnisstütze.
• Ein Term der Form o(N) stellt die Zahl 2 ∗ n dar.
• Ein Term der Form i(N) stellt die Zahl 2 ∗ n + 1 dar.
• Das Atom i stellt die Zahl 1 dar (höchstwertiges Bit).
Hinweis: Geben Sie für alle Funktionen, die Sie definieren, Typsignaturen an.
1. Wie würden Sie Binärzahlen mit Hilfe eines Datentypens in Haskell darstellen? Beachten Sie, dass Ihr
Darstellung bzgl. des Höchstwertisten Bits der Prolog-Variante entspricht. Im Folgenden verwenden wir
den Namen Bin für den neu definierten Datentypen.
2. Definieren Sie zwei Funktionen fromBin :: Bin -> Int und toBin :: Int -> Bin, die Ihren Datentypen in eine Zahl bzw. umgekehrt überführen. Im zweiten Fall betrachten wir nur positive Zahlen, die
größer als Null sind; alle anderen Werte sollen einen Fehler liefern.
3. Des Weiteren möchten wir Binärkodierungen spaßeshalber umkehren können; definieren Sie also eine
Funktion reverseBin :: Bin -> Bin. Der Aufruf fromBin (reverseBin (toBin 13)) soll z.B. 11
liefern, sprich aus 1101 wird 1011. Insbesondere können wir keinen führenden Nullen darstellen, so dass
diese wegfallen, sprich aus 1000 wird 1.
4. Zu guter Letzt wollen wir, dass der Datentyp eine schöne Ausgabe erhält. Geben Sie eine Implementierung
an, die den Datentyp Bin wie folgt ausgibt:
> show (toBin 8)
"IOOO"
10 Punkte
Aufgabe 5 - Buzz, buzz, wir brauchen buzz!
Das folgende Prolog-Programm definiert ein Prädikat replace(XS,YS), das die Zeichenfolge “bu” durch “zz”
ersetzt.
replace([]
, []).
replace([b,u|XS], [z,z|YS]) :- replace(XS, YS).
replace([X|XS] , [X|YS])
:- replace(XS, YS).
Als Beispiel betrachten wir die folgende Anfrage:
?- replace([b,u,b,u],Z).
Z = [z,z,z,z];
Z = [b,u,z,z];
Z = [b,u,z,z,];
Z = [b,u,b,u];
8
Durch Überlappung der zweiten und dritten Regel erhalten wir durch Backtracking insgesamt vier Lösungen,
da für jede mögliche Ersetzung von bu die Zeichenfolge auch erhalten bleiben kann.
1. Bearbeiten Sie eine der folgenden Aufgaben, um die Anfrage ?- replace([a,b,b,u],Res). zu beweisen.
Geben Sie für die Anfrage den entstehenden SLD-Baum an, der durch die SLD-Resolution aus der
Vorlesung entsteht; die Äste sollen dabei jeweils mit den Variablenbindungen beschriften werden.
oder
Beweisen Sie die Anfrage mit der Auswertungsstrategie von Prolog.
2. Modifizieren Sie die Implementierung von replace durch das Einfügen eines einzigen Cuts (!) so, dass das
Prädikat alle Vorkommen von bu durch zz ersetzt. Es dürfen keine anderen Änderungen vorgenommen
werden. So soll die Anfrage ?- replace([b,u,b,u],Z) nur noch Z = [z,z,z,z] als Ergebnis liefern.
Erklären Sie mit Hilfe von Teilaufgabe 1, in welchem Schritt der Cut in der Anfrage auftaucht und in
welchem Schritt welche Berechnungen wegfallen (Nummerierungen könnten hier hilfreich sein).
10 Punkte
Aufgabe 6 - Prolog und Unifikation
1. Wir betrachten das folgende Prolog-Programm.
invented(edison,lightbulb).
invented(colmeraurer,prolog).
iq(einstein,210).
iq(edison,160).
iq(waldorf,90).
genius(Person):- iq(Person,IQ), IQ > 150.
genius(Person):- invented(Person,_).
a) Was ist die erste Antwort von Prolog für die Anfrage ?- genius(A).?
b) Wie viele Antworten gibt uns Prolog insgesamt, wenn wir die Anfrage ?- genius(A) stellen? Sprich,
wir geben solange mit ; weitere Lösungen aus, bis die Anfrage terminiert. Zählen Sie dabei auch
alle vielfachen Vorkommen!
c) Viele vertreten die Meinung, dass Statler das Genie der beiden alten Herren der Muppet-Show ist.
Erklären Sie warum, die Anfrage ?- genius(statler) aber dennoch nicht erfüllt ist.
d) Mit welcher Anfrage können Sie alle Genies in einer Liste erhalten?
2. Mit welchen der Terme kann man ohwell(X, a(b,c), g(W, [H | T])) unifizieren? Insofern eine
Unifikation möglich ist, geben Sie den entsprechenden mgu an; ist keine Unifikation möglich, geben Sie
eine kurze Begründung bzgl. des ersten nicht aufzulösenden Disagreement Sets an (Sie müssen jedoch
nicht jeden Schritt des Unifikationsverfahrens anwenden, die letztendliche Substitution genügt).
a)
b)
c)
d)
e)
f)
g)
h)
[XH | XT]
ohwell(V)
ohwell([V | V1])
ohwell(X, a(b,c), g(W, [H | T]))
oh(X, a(b,c), g(W, [H | T]))
ohwell(r(b,c,s), a(G,H), g(wer, [GG]))
ohwell(r(b,QQ,E), a(G,H), G)
ohwell(X1, X2, g(234, []))
9
Herunterladen