fib (n+1)

Werbung
Funktionale Programmierung
ALP I
Funktionale Programmierung
Zusammengesetzte Datentypen in Haskell
WS 2012/2013
Prof. Dr. Margarita Esponda
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Zusammengesetzte Datentypen
Tupel
List
String
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Zusammengesetzte Datentypen
Tupel-Datentyp
Ein Tupel ist eine Ansammlung von zwei oder mehreren
Daten, die unterschiedliche Datentypen besitzen können.
Mit Hilfe von Tupeln können zusammengehörige Daten als
Einheit behandelt werden.
Beispiele:
Studierende
( "Peter" , "Meyer", 439990 ) :: ( String, String, Int )
( 2.5, 3.0 )
Prof. Dr. Margarita Esponda
:: ( Double, Double )
Punkt
Funktionale Programmierung
Tupel-Typ
Funktionsdefinition mit Tupeln:
distance :: (Double, Double) -> (Double, Double) -> Double
distance (x1,y1) (x2,y2) = sqrt (squareX + squareY )
where
squareX = (x1-x2) * (x1-x2)
squareY = (y1-y2) * (y1-y2)
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Tupel-Datentyp
rgbColor :: (Int, Int, Int) → [Char]
rgbColor (red, green, blue) = case (red, green, blue) of
(0,0,0)
→ "black"
(255,255,255) → "white"
Prof. Dr. Margarita Esponda
(255,0,0)
→ "red"
(0,255,0)
→ "green"
(0,0,255)
→ "blue"
otherwise
→ "other color"
Funktionale Programmierung
Tupel-Typ
Ein Tupel-Typ hat folgende allgemeine Form:
( t1 , t2 , … , tn ), wobei t1 , t2 , … , tn beliebige
Datentypen sind
Zwei einfache Funktionen für Tupel sind:
fst (x, y) = x
snd (x, y) = y
Die erwartete Tupel-Struktur wird in den Argumenten sichtbar
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Tupel-Typ
Funktionsdefinition mit Tupeln:
distance :: (Double, Double) -> (Double, Double) -> Double
distance p1 p2 = sqrt(xd^2 + yd^2)
where
xd = (fst p1) - (fst p2)
yd = (snd p1) - (snd p2)
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Pattern-Matching
myNot :: Bool -> Bool
myNot True
= False
myNot False = True
oder :: Bool -> Bool -> Bool
oder
oder
False False = False
x
y
= True
oder0 :: Bool -> Bool -> Bool
oder0
False False = False
oder0
False True = True
oder0
True False = True
oder0
True True = True
und :: Bool -> Bool -> Bool
und
True
True
=
True
und
_
_
=
False
beliebige Argumente vom Typ Bool
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Pattern-Matching
In Haskell ist es möglich durch Pattern-Matching eine Auswahl
verschiedener Funktionsgleichungen zu definieren.
Allgemeine Form:
f p11 p12 … p1n = e1
f p21 p22 … p2n = e2
…..
f pk1 pk2 … pkn = ek
Die pij Muster werden von oben nach unten und von links nach
rechts geprüft.
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Typ-Synonyme
Typ-Synonyme werden verwendet, um die Lesbarkeit von
Programmen mit Hilfe von aussagekräftigen Typ-Namen zu
verbessern.
Allgemeine Form:
type Typname = …….
Beispiele:
type Student = (String, String, Int)
type Point = (Double, Double)
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Typ-Synonyme
Funktionsdefinition mit Typ-Synomyme:
type Point = (Double, Double)
distance :: Point -> Point -> Double
distance (x1,y1) (x2,y2) = sqrt (sumSq (x1-x2) (y1-y2))
where
sumSq x y = x*x + y*y
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Typ-Synonyme
type Complex = (Double, Double)
realPart :: Complex -> Double
realPart ( real, img ) = real
imgPart :: Complex -> Double
Text
imgPart ( real, img ) = img
sumC :: Complex -> Complex -> Complex
sumC (r1,i1) (r2,i2) = (r1+r2, i1+i2)
absC :: Complex -> Double
absC ( real, img ) = sqrt( real*real + img*img )
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Rekursion
Rekursion ist ein fundamentales Konzept in der Mathematik
- eine Denkform für Problembeschreibung
- enge Beziehung zur mathematischen Induktion
Rekursion ist ein fundamentales Konzept in der Informatik
- eine Methode zur Problemlösung
Rekursive Funktionsdefinitionen sind die wichtigste
Programmiertechnik in funktionalen Programmiersprachen.
Prof. Dr. Margarita Esponda
13
Funktionale Programmierung
Rekursive Funktionen
Typisches Beispiel:
Wie viele
Permutationen kann
eine Reihe von
Objekten maximal
haben?
Die Fakultätsfunktion
factorial :: Int -> Int
factorial n = if n==0
then 1
else n * factorial (n-1)
factorial :: Int -> Int
factorial n | n==0
=1
| otherwise = n*factorial (n-1)
richtig aber nicht
schön
factorial :: Integer -> Integer
factorial n | n==0 = 1
| True
Prof. Dr. Margarita Esponda
= n*factorial (n-1)
Funktionale Programmierung
Rekursive Funktionen
Die Fakultätsfunktion
Pattern-Matching
factorial :: Int -> Int
factorial 0 = 1
factorial n = n * factorial (n-1)
bigFactorial :: Integer -> Integer
bigFactorial 0 = 1
bigFactorial n = n * bigFactorial (n-1)
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Rekursive Funktionen
Die Fakultätsfunktion
Pattern-Matching
factorial :: Int -> Int
factorial n = n * factorial (n-1)
factorial 0 = 1
Warning: Pattern match(es) are overlapped
In the definition of `factorial': factorial 0 = ...
Ok, modules loaded:
factorial 0
*** Exception: stack overflow
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Rekursive Funktionen
noch ein Klassiker:
Größter gemeinsamer Teiler von zwei natürlichen Zahlen a, b
Euklid (originaler Algorithmus)
ggt :: Integer → Integer → Integer
ggt p q | p>q
= ggt (p-q) q
| p==q = p
| p<q
Probleme?
Prof. Dr. Margarita Esponda
= ggt p (q-p)
Funktionale Programmierung
Rekursive Funktionen
ggt :: Integer → Integer → Integer
ggt p q | p>q = ggt (p-q) q
| p==q = p
| p<q = ggt p (q-p)
Probleme?
ggt 20 8
⇒ (20-8) 8
⇒ ggt 12 8
⇒ ggt (12-8) 8
⇒ ggt 8 4
⇒ ggt 4 4
⇒4
Prof. Dr. Margarita Esponda
ggt 8 0 ⇒ ggt (8-0) 0
⇒ ggt 8 0
⇒ ggt 8 0
.... :(
Funktionale Programmierung
Rekursive Funktionen
1. Lösung:
2. Lösung:
ggt a b
| b == 0
=a
| otherwise
= ggt b (a `mod` b)
ggt a b
| a == 0 && b == 0 = ???
Prof. Dr. Margarita Esponda
| b == 0
=a
| otherwise
= ggt b (a `mod` b)
Funktionale Programmierung
Pizzaproblem (Jakob Steiner, 1826)
Wie viele Pizza-Teile entstehen
maximal, wenn eine Pizza mit
n geraden Schnitten aufgeteilt
wird?
maxSurfaces :: Int -> Int
maxSurfaces 0 = 1
maxSurfaces n = maxSurfaces (n - 1) + n
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Rekursive Funktionen
Berechnung des goldenen Schnitts
Zwei positive reelle Zahlen stehen im Verhältnis der goldenen Zahl, wenn
a a+b
=
b
a
gilt,
Goldener Schnitt =
mit a > b > 0.
Φ = 1+
1
Φ
goldenRatio :: Int -> Double
goldenRatio n
| n == 0 = 1
| n > 0 = 1 + 1 / goldenRatio (n-1)
| otherwise = error "not defined for negative numbers"
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Fibonacci-Zahlen
Problem:
Zu Beginn eines Jahres gibt es genau ein Paar neugeborener
Kaninchen.
Ein Paar neugeborener Kaninchen ist erst nach einem Monat
fortpflanzungsfähig, sodass erst nach zwei Monaten ein
neues Kaninchenpaar zur Welt gebracht werden kann.
Jedes nicht neugeborene Kaninchen bekommt ein neues
Kaninchenpaar monatlich.
Wie viele Kaninchen gibt es nach einem Jahr, wenn keines
der Kaninchen stirbt?
Prof. Dr. Margarita Esponda
22
Funktionale Programmierung
1
Fibonacci-Zahlen
1
2
3
5
8
Prof. Dr. Margarita Esponda
23
Funktionale Programmierung
Fibonacci-Zahlen
Der Stammbaum einer Drohne
13
8
Ururgroßeltern 5
Urgroßeltern
3
Großeltern
2
Mutter
1
Drohne
Prof. Dr. Margarita Esponda
24
Funktionale Programmierung
Fibonacci-Zahlen
8
13
5
1
1
2
3
21
Prof. Dr. Margarita Esponda
25
Blumen
Fibonacci-Zahlen
1
2
3
5
8
13
21
34
26
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Fibonacci-Zahlen
fib(0)
0
+
fib(1)
fib(2)
1
1
Prof. Dr. Margarita Esponda
27
Funktionale Programmierung
Fibonacci-Zahlen
fib(0)
fib(1)
0
1
Prof. Dr. Margarita Esponda
fib(2)
+
1
fib(3)
2
28
Funktionale Programmierung
Fibonacci-Zahlen
fib(0)
fib(1)
fib(2)
0
1
1
Prof. Dr. Margarita Esponda
fib(3)
+ 2
fib(4)
3
29
Funktionale Programmierung
Fibonacci-Zahlen
fib(0)
fib(1)
fib(2)
0
1
1
Prof. Dr. Margarita Esponda
fib(3)
2
+
fib(4)
3
fib(5)
5
30
Funktionale Programmierung
Fibonacci-Zahlen
fib(0)
fib(1)
fib(2)
fib(3)
0
1
1
2
.....
fib(4) fib(5)
3
fib(n-2) + fib(n-1)
5
fib(6)
fib(7)
+ 8
+
13
.....
fib(n)
Formale rekursive Definition:
fib ( 0 ) = 0
fib ( 1 ) = 1
fib ( n ) = fib ( n-2 ) + fib ( n-1 )
Prof. Dr. Margarita Esponda
für alle
n>1
31
Funktionale Programmierung
Berechnung der Fibonacci-Zahlen
1. Lösung
Beispiel:
fib 7
fib 7
fib 5
fib 3
fib 1
fib 0
fib 1
fib 6
fib 4
fib 2
fib 2
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
fib 4
fib 3
fib 2
fib 5
fib 3
fib 3
fib 4
fib 0 fib 1 fib 1 fib 2 fib 0 fib 1 fib 1 fib 2 fib 1 fib 2 fib 2 fib 3
fib 0 fib 1
fib 0 fib 1 fib 0 fib 1
wiederholte Berechnungen der fib-Funktion
Prof. Dr. Margarita Esponda
fib 1 fib 2
fib 0 fib 1
Berechnung der Fibonacci-Zahlen
Beispiel:
fib 7
fib 7
fib 5
fib 3
fib 1
fib 0
fib 4
fib 2
fib 1
fib 6
fib 2
fib 4
fib 3
fib 2
fib 5
fib 3
fib 3
fib 4
fib 0 fib 1 fib 1 fib 2 fib 0 fib 1 fib 1 fib 2 fib 1 fib 2 fib 2 fib 3
fib 0 fib 1
Fallgrube
Wenn wir fib 40 mit unserer
rekursiven Implementierung
berechnen,
wird:
fib 0 fib 1 fib 0 fib 1
fib 1 fib 2
fib 0 fib 1
fib 39 einmal berechnet
fib 38 2 mal berechnet
fib 37 3 mal berechnet
fib 36 5 mal berechnet
fib 35 8 mal berechnet
...
fib 0 165 580 141 mal berechnet
Beim Aufruf von fib 40 werden 331 160 281 Funktionsaufrufe gemacht
Funktionale Programmierung
Berechnung der Fibonacci-Zahlen
Wie viele Reduktionsschritte brauchen wir, um fib n zu berechnen?
fib 0
1
fib 1
+
1
1
=
+
fib 2
2
2
2
fib 3 fib 4
5
3
=
+
fib 5
fib 6
8
13
Reduktionen
3
3
3
=
+
5
5
3
=
+
8
5
=
13
Die Anzahl der Reduktionen für fib n ist gleich fib (n+1)
Die Anzahl der rekursive Aufrufe ist eine
exponentielle Funktion von n.
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Berechnung der Fibonacci-Zahlen
2. Lösung
quickFib funktioniert nur, wenn diese mit
den ersten zwei Fibonacci-Zahlen
gestartet wird.
fib' n = quickFib 0 1 n
Zähler
where
quickFib a b 0 = a
quickFib a b n = quickFib b (a+b) (n-1)
Innerhalb jedes rekursiven Aufrufs wird eine neue Fibonacci-Zahl berechnet und
der Zähler verkleinert. Die neue Zahl und ihr Vorgänger werden beim nächsten
rekursiven Aufruf als Parameter weitergegeben.
Anzahl der Reduktionen
Für die Berechnung von quickFib n benötigen wir n Reduktionen,
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Fibonacci-Zahlen
3. Lösung mit Tupeln:
nextFib :: (Integer, Integer) -> (Integer, Integer)
nextFib (a,b) = (b, a+b)
fib n = fst ( fibTuple n ) Text
fibTuple n | n==0
= (0, 1)
| otherwise = nextFib (fibTuple (n-1))
Prof. Dr. Margarita Esponda
36
Funktionale Programmierung
Listen
Listen sind die wichtigsten Datenstrukturen in funktionalen
Programmiersprachen
Listen stellen Sammlungen von Objekten dar, die den gleichen
Datentyp besitzen
Listen sind dynamische Datenstrukturen, die mit Hilfe folgender
Daten-Konstruktoren erzeugt werden können
Symbol
Prof. Dr. Margarita Esponda
Name
Bedeutung
[]
nil
leere Liste
(:)
cons
am Anfang anfügen
Funktionale Programmierung
Listen
Listen sind rekursive Strukturen:
Eine Liste ist entweder leer
[]
oder ein konstruierter Wert, der aus einem Listenkopf x
und einer Restliste xs besteht.
head
tail
x : xs
Der Typ einer Liste, die Elemente des Typs t enthält, wird
mit [t] bezeichnet.
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Ausdrücke mit Listen
Beispiele:
Ausdruck
Datentyp
[1, 2, 3]
::
[Integer]
1: [0,3,7]
::
[Integer]
[ [0.3, 0.0], [] ]
::
[[Double]]
'a' : "Hello"
::
[Char]
[( 3, 0 ), ( 2, 1)]
::
[ (Integer, Integer) ]
[ True, True, False ]
::
[ Bool ]
Allgemeine Syntax:
[ e1, e2, e3, … ,en ]
Prof. Dr. Margarita Esponda
Syntaktische Abkürzung:
e1:[e2:[e3: … :en:[]]]
e1:e2: … :en:[]
Funktionale Programmierung
Ausdrücke mit Listen
Beispiele:
equiv.
[1, 2, 3]
1:[2, 3]
1 : 2 : 3 : []
"hello"
['h', 'e', 'l', 'l', 'o']
'h' : "ello"
Prof. Dr. Margarita Esponda
[( 3, 0 ), ( 2, 1)]
( 3, 0 ) : [( 2, 1)]
[[3, 0 ], [2, 1]]
[3, 0] : [2, 1] : []
Funktionale Programmierung
Funktionen mit Listen
kopf :: [ Integer ] -> Integer
kopf (x:xs) = x
kopf [] = error "ERROR: empty list"
rumpf :: [ Integer ] -> [ Integer ]
rumpf (x:xs) = xs
rumpf [] = error "ERROR: empty list"
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Funktionen mit Listen
Addiert alle Zahlen innerhalb einer Liste
summe :: [Integer] -> Integer
summe
ls
=
if
ls == []
then
0
else ( kopf ls ) + summe (rumpf ls)
Lösung mit Pattern-Matching über der Listenstruktur
summe :: [Integer] -> Integer
summe
[]
summe
(x : xs) =
Prof. Dr. Margarita Esponda
=
0
x + summe xs
Funktionale Programmierung
Funktionsdefinitionen mit Listen
multList :: [Integer] -> Integer
multList [] = error "the function is not defined for []"
multList [x] = x
multList (x:xs) = x * multList xs
laenge :: [Int] -> Int
laenge [] = 0
laenge (x:xs) = 1 + laenge xs
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Zehnersystem → Binärsystem
42 10
=
div 2 mod 2
101010 2
42
0
21
1
10
0
5
1
2
1
0
0
1
dec2bin :: Int -> [Int]
dec2bin
n | n<2
= [n]
| otherwise = dec2bin (n`div`2) ++ [n `mod`2]
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Funktionen mit Listen
Verkettungsoperator
drehe [] = []
drehe (x:xs) = drehe xs ++ [x]
drehe [1,2,3] ⇒ drehe [2,3] ++ [1]
⇒ drehe [3] ++ [2] ++ [1]
⇒ drehe [] ++ [3] ++ [2] ++ [1]
⇒ [] ++ [3] ++ [2] ++ [1]
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Funktionen mit Listen
1011012 = 1*25 + 0*24 + 1*23 + 1*22 + 0*21 + 1*20
= 2(2(2(2(2(1)+0)+1)+1)+0)+1
binary2decimal xs = bin2dec ( drehe xs)
bin2dec :: [Int] -> Int
bin2dec [] = 0
bin2dec (x:xs) = x + 2*(bin2dec xs)
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Funktionen mit Listen
bitXOr :: [Int] -> [Int] -> [Int]
bitXOr [] [] = []
bitXOr (x:xs) (y:ys) = (exoder x y): (bitXOr xs ys)
bitXOr _ _ = error "the two lists are not of the same length"
exoder :: Int -> Int -> Int
exoder x y | x==y
=0
| otherwise = 1
Prof. Dr. Margarita Esponda
Herunterladen