Grundlagen der Programmierung 2 Aufgabenblatt Nr. 7 Aufgabe 1

Prof. Dr. Manfred Schmidt-Schauß
Künstliche Intelligenz/Softwaretechnologie
Fachbereich Informatik und Mathematik/ Institut für Informatik
Goethe-Universität Frankfurt am Main
Grundlagen der Programmierung 2
Sommersemester 2015
Aufgabenblatt Nr. 7
Abgabe: Mittwoch 03. Juni 2015 vor! der Vorlesung
Aufgabe 1 (25 Punkte)
Ziel dieser Aufgabe ist das Implementieren von zwei Stackmaschinenprogrammen. Im Rahmen einer
aktuellen Bachelorarbeit wird an der Professur ein Online-System zum Lernen und Ausprobieren von
Stackmaschinenprogrammen entwickelt, welches Sie zum Lernen und Testen verwenden können.
hine
mac
tack
e/s
t.d
kfur
fran
niik.u
rmat
o
f
n
.i
w.ki
w
w
/
/
ttp:
h
Wir wären sehr dankbar, wenn Sie nach dem Ausprobieren auch den Bewerten-Knopf drücken und
das System bewerten und Anregungen zur Verbesserung geben.
Das System ist unter http://www.ki.informatik.uni-frankfurt.de/stackmachine verfügbar.
Neben den beiden Teilaufgaben gibt es im System auch einige Einführungsaufgaben, die Ihnen den
Einstieg erleichtern sollen (für die Lösung der Einführungsaufgaben gibt es keine Punkte).
a) Geben Sie ein Stackmaschinenprogramm an, das für jeden Stack der Form [a, b] (wobei a oben
auf dem Stack liegt) als Resultat den Stack [l, m, n] liefert, wobei l = 2∗a+2∗b, m = 3∗(2∗a−b)
und n = b − 2 ∗ a.
(10 Punkte)
b) Geben Sie ein Stackmaschinenprogramm an, das einen nicht-leeren Stack erwartet, dessen oberstes Element eine positive Ganzzahl ist und prüft, ob das oberste Element gerade oder ungerade ist, und im ersten Fall das Element durch 1 und im anderen Fall durch 0 ersetzt. Verwenden
Sie dafür nicht die Division, sondern ziehen Sie solange 2 ab, bis sie 0 oder 1 erreichen.
Tipp: Verwenden Sie Sprungmarkierungen und Befehle.
(15 Punkte)
1
Aufgabe 2 (35 Punkte)
Wie in der Vorlesung und im Skript erläutert, kann die Auswertung einer Stackmaschine mit den
Befehlen pop, pushK, push, slide, branchz, jump und mit arithmetischen Operationen +, − und ∗
sowie Marken wie folgt als Funktion I definiert werden:
I
I
I
I
I
I
I
I
I
I
Programm
[]
(pop : prest)
((pushK k) : prest)
((push i) : prest)
(+ : prest)
(− : prest)
(∗ : prest)
((slide m n) : prest)
(marke : prest)
((branchz marke) : prest)
I (jump marke) : prest)
Stack
stack
(a : srest)
stack
stack
(a : b : srest)
(a : b : srest)
(a : b : srest)
stack
stack
(a : srest)
Kopie
prg
prg
prg
prg
prg
prg
prg
prg
prg
prg
stack
prg
Nächster Aufruf (Resultat)
stack
I prest srest prg
I prest (k : stack ) prg
I prest ((stack !!i) : stack ) prg
I prest (b + a : srest) prg
I prest (b − a : srest) prg
I prest (b ∗ a : srest) prg
I prest (take m stack ++ (drop (n + m) stack )) prg
I prest stack prg
if (0 == a) then
I (dropWhile (marke /=) prg) srest prg
else I prest srest prg
−→ I (dropWhile (marke /=) prg) stack prg
−→
−→
−→
−→
−→
−→
−→
−→
−→
−→
a) Führen Sie das Stackmaschinenprogramm (bestehend aus 15 Befehlen)
1
2
3
4
5
pushK 2;
push 0;
pushK 4;
marke1.;
push 2;
-;
push 0;
8 pushK 2;
9 slide 1 2;
10 -;
6
11
7
12
13
14
15
push 0;
branchz marke2;
jump marke1;
marke2.;
pop
beginnend mit leerem Stack per Hand entsprechend der obigen Regeln aus, indem Sie das Programm und den Stack nach Ausführung jedes Befehls angeben.
(10 Punkte)
b) In dieser Aufgabe soll die Stackmaschine in Haskell implementiert werden. Befehle der Stackmaschine werden durch den folgenden Datentyp Kommando repräsentiert. Für Marken werden
dabei Zahlen verwendet und Mult, Add und Sub stehen für die arithmetischen Operationen:
data Befehl = PushK Int | Pop | Push Int | Mult | Add | Sub | Mark Marke
| Jump Marke | Branchz Marke | Slide Int Int
deriving (Eq,Show)
type Marke = Int
Ein Stackmaschinenprogramm ist eine Liste von Befehlen und der Stack ist eine Liste von Zahlen
type StackProgramm = [Befehl]
type Stack = [Int]
Implementieren Sie in Haskell eine Funktion run :: StackProgramm -> Stack, die ein Stackmaschinenprogramm erwartet und den resultierenden Stack als Ergebnis liefert. Implementieren
Sie hierfür zunächst eine Hilfsfunktion
interpretiere :: StackProgramm -> Stack -> StackProgramm -> Stack
die genau die oben angegebene Funktion I in Haskell umsetzt, und rufen Sie diese innerhalb von
run auf.
(25 Punkte)
2
Aufgabe 3 (40 Punkte)
Wir betrachten erneut die Pferdeprogramme von Aufgabenblatt 6 und deren Haskell-Repräsentation
vom Typ Code:
type Code = [Command]
data Command = Hopp (Dir,Dir) | Wiederhole Int Code
deriving (Show)
data Dir = N | W | O | S
deriving (Show)
Ziel der Aufgabe ist es, Zwischencode für die Stackmaschine aus Aufgabe 1 aus Pferdeprogrammen zu
erzeugen. D.h. Sie sollen eine Funktion
codeGenerierung :: Code -> StackProgramm
in Haskell implementieren, die aus einem Pferdeprogramm ein Stackmaschinenprogramm erzeugt.
Dafür modellieren wir den Zustand des Pferdes wie folgt im Stack der Maschine:
Der Zustand wird durch zwei Einträge im Stack repräsentiert: [posx,posy], wobei posx und posy die
Position des Pferdes auf der x-Achse und y-Achse angeben.
Da das Pferd am Anfang an Position (0,0) steht, ist der Stack am Anfang [0,0].
Hinweise:
• Implementieren Sie codeGenerierung, indem Sie zunächst den Code für jeden der einzelnen
Befehle programmieren. Dabei sollte der Stack vor Ausführung des Codes die Form [posx,posy]
haben und nach Ausführung eines Befehls von der Form [posx’,posy’] sein, wobei posx’ und
posy’ den neuen Zustand des Pferdes beschreibt.
• Der Code für Wiederhole i code ist der schwierigste und sollte Sprungmarkierungen benutzen
und nicht den Code code i-mal entfalten, denn dies führt zu sehr langen Stackmaschinenprogrammen.
Verknüpfen Sie den Parser von Aufgabenblatt 6, den Stackmaschinenauswerter von Aufgabe 1 dieses
Blattes und die Kodegenerierung dieser Aufgabe, um Pferdeprogramme auszuführen.
3