AB6 Low-Level Programmierung
Implementieren Sie die folgenden Funktionen nur unter Verwendung der bereits importierten Funktionen. Folgende Sprachkonstrukte dürfen nicht verwendet werden:
if ... then ... else ...
(benutzen Sie stattdessen if'
sofern importiert)
- Guards
- List Comprehensions:
[(i,j) | i <- [1,2], j <- [3,4]]
Eine Zählmaschine besteht aus Registern, welche alle eine natürliche Zahl (inkl. 0) enthalten. Der Wert in jedem Register kann um eins erhöht oder verringert werden. Falls ein Register eine 0 enthält und verringert werden soll, so bleibt eine 0 im Register stehen. Außerdem kann geprüft werden, ob in einem Register die Zahl 0 steht. Folgende Funktionen stehen zur Verfügung, um eine Zählmaschine zu steuern.
inc :: CM -> Int -> CM
dec :: CM -> Int -> CM
isZero :: CM -> Int -> Bool
Die Funktion
inc
(bzw.
dec
) erhöht (bzw. verringert) Register
arg2
um eins. Das erste Register ist
1
.
Die Funktion
isZero
ist wahr gdw. das Register
arg2
eine 0 enthält.
move :: CM -> CM
copy :: CM -> CM
add :: CM -> CM
mult :: CM -> CM
Für eine Zählmaschine mit \(k\) Registern soll \(R_i\) den Wert zu Beginn und \(R_i'\) den Wert zu Ende der Berechnung in Register \(i\) bezeichnen für alle \( 1 \leq i \leq k \).
Die Funktion
move
soll für eine Zählmaschine mit 2 Registern den Inhalt des ersten Registers ins zweite übertragen, also \(R_2' = R_1\).
Die Funktion
copy
soll für eine Zählmaschine mit 3 Registern den Inhalt des ersten Registers ins zweite kopieren, also \(R_1' = R_2' = R_1\).
Die Funktion
add
soll für eine Zählmaschine mit 3 Registern den Inhalt der ersten zwei Register addieren und ins dritte schreiben, also \(R_3' = R_1 + R_2\).
Die Funktion
mult
soll für eine Zählmaschine mit 4 Registern den Inhalt der ersten zwei Register multiplizieren und ins dritte schreiben, also \(R_3' = R_1 \cdot R_2\).
Beispiele ('
_
' steht für eine beliebige Zahl):
(move (CM [13,2])) = (CM [_,13])
(copy (CM [5,4,6])) = (CM [5,5,_])
(add (CM [3,4,19])) = (CM [_,_,7])
(mult (CM [2,3,0])) = (CM [_,_,6,_])
Eine Stapelmaschine ist eine Verallgemeinerung von Zählmaschinen, bei der Strings in den Registern enthalten sind. Eine solche Maschine verfügt über die folgenden Operationen und Prädikate. Das letzte Zeichen eines Strings aus einem Register kann entfernt werden. Ans Ende eines Strings aus einem Register kann ein beliebiges Zeichen aus dem Alphabet angehängt werden. Es kann geprüft werden, ob ein String in einem Register leer ist oder ob das letzte Zeichen dieses Strings gleich einem bestimmten Zeichen ist. Folgende Funktionen stehen zur Verfügung, um eine Stapelmaschine zu steuern.
push :: SM -> Int -> Char -> SM
pop :: SM -> Int -> SM
isEmpty :: SM -> Int -> Bool
isChar :: SM -> Int -> Char -> Bool
Die Funktion
push
fügt das Zeichen
arg3
ans Ende des Strings in Register
arg2
hinzu.
Die Funktion
pop
entfernt das letzte Zeichen des Strings in Register
arg2
(String bleibt unverändert falls leer).
Die Funktion
isEmpty
ist wahr gdw. der String in Register
arg2
leer ist.
Die Funktion
isChar
ist wahr gdw. das letzte Zeichen des Strings in Register
arg2
gleich
arg3
ist.
reverse :: SM -> SM
move :: SM -> SM
copy :: SM -> SM
concat :: SM -> SM
substr :: SM -> SM
Für eine Stapelmaschine mit \(k\) Registern soll \(R_i\) den Wert zu Beginn und \(R_i'\) den Wert zu Ende der Berechnung in Register \(i\) bezeichnen für alle \( 1 \leq i \leq k \).
Die Funktion
reverse
soll für eine Stapelmaschine mit 2 Registern den Inhalt des ersten Registers umgedreht ins zweite Register schreiben, also \(R_2' = \text{reverse}(R_1)\).
Die Funktion
move
soll für eine Stapelmaschine mit 3 Registern den Inhalt des ersten Registers ins zweite Register schreiben, also \(R_2' = R_1\).
Die Funktion
copy
soll für eine Stapelmaschine mit 3 Registern den Inhalt des ersten Register ins zweite kopieren, also \(R_1' = R_2' = R_1\).
Die Funktion
concat
soll für eine Stapelmaschine mit 3 Registern den String aus Register 2 an den String aus Register 1 anhängen und in Register 3 schreiben, also \(R_3' = R_1 R_2\).
Die Funktion
substr
soll für eine Stapelmaschine mit 4 Registern den Teilstring von \(R_1\), welcher ab dem \((|R_2|+1)\)-ten Zeichen beginnt und Länge \(|R_3|\) hat in Register 4 schreiben.
Sie können davon ausgehen, dass die Strings in den Stapelmaschinen nur aus den Zeichen
'a','b','c'
bestehen.
Beispiele:
(reverse (SM ["abcaa","abb"])) = (SM [_,"aacba"])
(move (SM ["babc","abb","cab"])) = (SM [_,"babc",_])
(copy (SM ["babc","abb","cab"])) = (SM ["babc","babc",_])
(concat (SM ["cc","abab","ba"])) = (SM [_,_,"ccabab"])
(substr (SM ["abcabc","a","aaa",""])) = (SM [_,_,_,"bca"])