AB1 Nicht-rekursive Ausdrücke
Implementieren Sie die folgenden Funktionen durch
nicht-rekursive Ausdrücke (einzige Ausnahme ist Teil 2) und nur unter Verwendung der bereits importierten Funktionen. Außerdem dürfen folgende Sprachkonstrukte nicht verwendet werden:
Hinweise (gelten auch für alle weiteren AB):
- Hinweise zur Abgabe der Arbeitsblätter finden Sie in der Readme.html
- Code-Beispiel finden Sie in der Datei
example/Test.hs
- das i-te Argument einer Funktion wird als
arg
i bezeichnet. Zum Beispiel wird das zweite Argument von f :: Int -> Int -> Int -> Int
mit arg2
bezeichnet
- Sie können Funktionen innerhalb eines Teils in beliebiger Reihenfolge lösen (z.B. um spätere Funktionen zu verwenden, um vorherige zu definieren)
- negative Zahlen: soweit nicht explizit anders angegeben, müssen Funktionen auch erwartungsgemäß für negative Zahlen funktionieren
- sollte die Spezifikation für eine Funktion unklar sein (wie soll die Ausgabe für eine bestimmte Eingabe aussehen), fragen Sie nach!
Für dieses AB sollten Sie sich die Funktionen
map
,
filter
,
reduce
,
foldl
und
foldr
genauer anschauen.
Sie können davon ausgehen, dass
arg1
für alle Funktionen in diesem Teil (mit Ausnahme von
bigAnd2
) mindestens ein Element enthält.
minimum :: [Int] -> Int
maximum :: [Int] -> Int
Die Funktionen geben ein minimales bzw. maximales Element der Liste
arg1
zurück.
bigAnd :: [Bool] -> Bool
bigOr :: [Bool] -> Bool
bigXor :: [Bool] -> Bool
Die Funktion
bigAnd
gibt wahr zurück gdw. alle Elemente in
arg1
wahr sind.
Die Funktion
bigOr
gibt wahr zurück gdw. mindestens ein Element in
arg1
wahr ist.
Die Funktion
bigXor
gibt wahr zurück gdw. eine ungerade Anzahl von Elementen in
arg1
wahr sind.
sum :: [Int] -> Int
alternatingSum :: [Int] -> Int
alternatingSum2 :: [Int] -> Int
Die Funktion
sum
gibt die Summe aller Elemente in
arg1
zurück.
Die Funktion
alternatingSum
gibt die alternierende Summe aller Elemente in
arg1
zurück. Für
[1,2,3,4,5]
ist das
1 - 2 + 3 - 4 + 5
.
Die Funktion
alternatingSum2
ist eine Variante, bei der
+
und
-
vertauscht werden. Für
[1,2,3,4,5]
ist das
1 + 2 - 3 + 4 - 5
.
bigAnd2 :: [Bool] -> Bool
Die Funktion
bigAnd2
gibt wahr zurück gdw. alle Elemente in der Liste wahr sind oder die Liste leer ist.
Für diesen Teil dürfen (und müssen) Sie rekursive Ausdrücke verwenden.
infiniteList :: Int -> [Int]
listFromTo :: Int -> Int -> [Int]
Die Funktion
infiniteList
gibt die unendliche Liste zurück, welche alle
Int
beginnend ab
arg1
in aufsteigender Reihenfolge enthält.
Die Funktion
listFromTo
gibt die Liste zurück, welche alle
Int
beginnend von
arg1
bis
arg2
in aufsteigender Reihenfolge enthält. Beispiele:
listFromTo 2 5 = [2,3,4,5]
listFromTo 2 1 = []
fibTree :: (Tree Int)
fTree :: (Int -> Int) -> (Tree Int)
Die Funktion
fibTree
ist der unendliche binäre Baum, welcher die Fibonacci-Sequenz (1, 1, 2, 3, 5, 8, 13, ...) beschreibt. Das erste Kind ist der entsprechende Wert aus der Sequenz.
Beispiel
1
1
2
1
3
2
4
3
5
5
6
8
7
13
...
Die Funktion
fTree
ist eine Verallgemeinerung von
fibTree
für beliebige Sequenzen. Das erste Kind eines Knotens mit dem Wert
i
enthält den Wert
f i
, wobei
f = arg1
.
Beispiel
1
f 1
2
f 2
3
f 3
4
f 4
5
f 5
6
f 6
7
f 7
...
crossList :: [a] -> [b] -> [(a,b)]
genCrossList :: [[a]] -> [[a]]
Die Funktion
crossList
ist das kartesische Produkt zweier Listen.
Beispiel:
crossList [1,2] [3,4] = [(1,3),(1,4),(2,3),(2,4)]
Die Funktion
genCrossList
ist das kartesische Produkt verallgemeinert auf beliebig viele Argumente, welche als Elemente der Liste
arg1
repräsentiert werden. Sie können davon ausgehen, dass
arg1
mindestens ein Element enthält. Beispiele:
genCrossList [[1,2],[3,4],[5,6]] = [[1,3,5],[1,3,6],[1,4,5],[1,4,6],[2,3,5],[2,3,6],[2,4,5],[2,4,6]]
genCrossList [[1,2,3]] = [[1],[2],[3]]
Tipp zu genCrossList
(falls Sie Probleme haben, diese Funktion zu implementieren, versuchen Sie den folgenden Code zu vervollständigen)
genCrossList lst = foldl crossList2 acc lst'
where
crossList2 x y = map g ?
where
g (lst,el) = append el lst
lst' = ?
acc = map f ?
where
f el = [el]
Die Funktion
primes
gibt die ersten
arg1
(≥ 0) Primzahlen zurück. Beispiele:
primes 5 = [2,3,5,7,11]
primes 0 = []
Tipp zu primes
Schreiben Sie eine Funktion ohne Eingabeparameter, welche die unendliche Liste aller Primzahlen zurückgibt.
type Base = Int
toDigits :: Base -> Int -> [Int]
fromDigits :: Base -> [Int] -> Int
length :: Base -> Int -> Int
Die Funktion
toDigits
wandelt die Zahl
arg2
(≥ 0) in eine Liste von Ziffern zur Basis
arg1
(≥ 2) um. Das erste Element der Liste ist die Ziffer mit dem höchsten Stellenwert (für Basis 2 also das most significant bit). Beispiele:
toDigits 2 4 = [1,0,0]
toDigits 10 9876 = [9,8,7,6]
Die Funktion
fromDigits
ist die Umkehrfunktion von
toDigits
. Das heißt, es gilt
fromDigits b (toDigits b x) == x
. Sie können davon ausgehen, dass jedes Element aus
arg2
zwischen 0 und (
arg1
- 1) liegt und
arg2
mindestens ein Element enthält. Beispiele:
fromDigits 2 [1,0,0] = 4
fromDigits 10 [9,8,7,6] = 9876
Die Funktion
length
gibt die Länge der Zahl
arg2
zur Basis
arg1
zurück. Beispiele:
length 2 4 = 3
length 10 9876 = 4
Eine Zahl bestehend aus \(n \geq 1\) Ziffern \(x_1, x_2, \dots, x_n\) zur Basis \(b \geq 2\) ist definiert als
$$\sum_{i=1}^n x_i \cdot b^{i-1}$$
Hinweis zu find
und zip
- der Ausdruck
find f (infiniteList 1)
gibt die erste Zahl x
≥ 1 zurück, für die gilt (f x) == True
- der Ausdruck
zip [4,5,6] (infiniteList 7)
gibt [(4,7),(5,8),(6,9)]
zurück
Tipp zu toDigits
Schreiben Sie eine Funktion, welche die i-te Ziffer einer Zahl für eine gegebene Basis berechnet.