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
argi 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.