Informatik A

Werbung
Teillösungen zum 13. und letzten Aufgabenblatt zur Vorlesung
Informatik A
(Autor: Florian Schmidt)
1. Reguläre Sprachen
Aus der Vorlesung ist bekannt, dass zu jeder regulären Sprache L ein DFA existiert,
der genau alle w ∈ L akzeptiert. Umgekehrt ist die Menge aller Wörter, die ein DFA
erkennt, immer eine reguläre Sprache.
Zu den gegebenen Sprachen L1 und L2 existieren also zwei endliche deterministische
Automaten A1 und A2 . Es recht zu zeigen, dass zu Lc1 , L1 \ L2 , L1 ∩ L2 und Lrev
endliche Automaten existieren, die die jeweilige Sprache erkennen.
(a) Sei A1 = (Σ, Q, s0 , δ, F ) der DFA für L1 und sei Ac1 der DFA für die Komplementärsprache Lc1 gegeben durch (Σ, Q, s0 , δ, F c ). In Ac sind genau alle Zustände
akzeptierend , die in A1 nicht akzeptierend sind und umgekehrt, mithin F c = Q\F .
Für L1 ∩L2 lässt sich ein Automat B = (Σ, Q, s0 , δ, F ) aus A1 = (Σ1 , Q1 , s1 , δ1 , F1 )
und A2 = (Σ2 , Q2 , s2 , δ2 , F2 ) wie folgt konstruieren: Die neue Zustandsmenge besteht aus allen Kombinationen der Zustände von A1 und A2 , also
Q = Q1 × Q2 = {(p, q) | p ∈ Q1 , q ∈ Q2 }. Wenn einer der neuen Zustände aus
einem akzeptierenden Zustand von A1 und aus einem akzeptierenden Zustand
von A2 besteht, soll er akzeptierend im neuen Automaten B sein: F = (F1 × F2 ).
Startzustand von B ist der Zustand, der aus den beiden Startzuständen von A1
und A2 gebildet wurde: s0 = (s1 , s2 ) .
Die Übergangsfunktion δ(σ, (p, q)) = (δ1 (σ, p), δ2 (σ, q)) simultiert die gleichzeitige
Ausführung von A1 und A2 . B akzeptiert dabei nur, wenn beide Automaten A1
und A2 akzeptieren würden. Somit erkennt B genau die Wörter aus L1 ∩ L2 .
Alternativ: L1 ∩ L2 = (Lc1 ∪ Lc2 )c .
Da Sprachen Mengen von Wörtern sind, lässt sich L1 \ L2 als L1 ∩ LC
2 ausdrücken. Reguläre Sprachen sind wie gezeigt unter Komplement und Durchschnitt
abgeschlossen. Also ist auch L1 \ L2 wieder eine reguläre Sprache.
(b) Sei A der Automat, welcher die reguläre Sprache L erkennt. In Arev sollen alle
Zustände aus A enthalten sein, wobei die Übergänge jeweils umgedreht wurden.
Ist δ(σ, p) = q, so sei p ∈ δrev (σ, q). Der Startzustand s0 aus A ist einziger akzeptierender Zustand in Arev . In Arev kommt ein neuer Zustand sstart hinzu, welcher mit allen akzeptierenden Zuständen aus A mittels -Übergang verbunden ist:
δrev (, sstart ) = F . Der neue Zustand sstart soll Startzustand in Arev sein.
Arev akzeptiert also genau dann, wenn einer der Wege von einem akzeptierenden
Zustand in A zum Startzustand in A führt. Das sind genau alle Wörter in Lrev . Arev
ist ein NFA und kann demnach in einen äquivalenten DFA umgewandelt werden.
Somit ist Lrev regulär.
2. Haskell I
(a) Alle Zahlen, die um eins erhöht größer als 0 sind, müssen vorher größer als −1
gewesen sein. Somit ist sec2 der Asudruck >(-1). Weil alle Zahlen um eins erhöht
werden müssen, ist sec1 der Ausdruck +1.
(b) Der
Wert
ist
[(n,2^n) | n<-[0..]].
[(0,1),(1,2),(2,4),(3,8),(4,16),...]
bzw.
(c) drop lässt die ersten n Elemente einer Liste weg und drop lässt alle Elemente nach
dem n-ten Element weg. Somit ist das Ergebnis die Liste [" i","nfa123"].
3. Haskell II, Algebraische Typen
(a) data StammBaum = Nil | Knoten (String, Int) StammBaum StammBaum deriving Show
(b)
durchSchnitt :: StammBaum -> Float
durchSchnitt xs = fromIntegral (sum (alter xs)) / fromIntegral (length (alter xs)
where
alter :: StammBaum -> [Int] -- Extrahiert die Liste aller Alterszahlen
alter Nil = []
alter (Knoten (a,b) l r) = [b] ++ alter l ++ alter r
(c)
anfrageName :: [StammBaum] -> String -> [StammBaum]
anfrageName xs name = concat(map (sucheNamen name) xs)
where
-- Sucht alle Teilbäume, die namen als Wurzel haben
sucheNamen :: String -> StammBaum -> [StammBaum]
sucheNamen name Nil = []
sucheNamen name (x@(Knoten (n,a) l r))
| n == name = [x] ++ sucheNamen name l ++ sucheNamen name r
| otherwise = sucheNamen name l ++ sucheNamen name r
4. Blockcode
(a) Für Blockcodelänge 15 gibt es 215 Codewörter über dem Alphabeth {0, 1}. Der
betrachtete Code soll 1-fehlerkorrigierend sein. Für ein Codewort z.B. w =
010011010110110 sollen also alle Codewörter, welche genau einen Fehler aufweisen, ebenfalls auf w decodiert werden. Sie stehen als Codewörter nicht mehr zur
Verfügung. Für w gibt es genau 15 Codewörter, welche genau einen Fehler aufweisen: 110011010110110, 000011010110110, 011011010110110 usw. Jedes Codewort
verbraucht also 1 + 15 = 24 mögliche Codewörter. Das bedeutet, dass es höchstens
215
= 211 Codewörter geben kann.
24
(b) Gegeben seien 128 verschiedene Zeichen mit relativen Häufigkeiten ihres Auftretens. Dabei sei die maximale auftretende Häufigkeit eines Zeichens kleiner als das
Doppelte der minimalen Häufigkeit. Beweisen Sie, dass dann ein Blockcode (was
ist dessen Blocklänge ?) schon ein optimaler Präfixcode ist.
Lösung: Der Blockcode hat Länge 7 wegen 27 = 128.
Optimale Präfixcodes werden von der Huffman-Codierung erzeugt, wir überlegen
uns, dass dabei der volle balancierte Binärbaum mit Tiefe 7 entsteht. Huffman
geht greedy vor. Seien p1 , p2 , . . . , pn die aufsteigend sortierten Häufigkeiten. Nach
Voraussetzung werden zuerst p1 mit p2 vereinigt, die Liste der aufsteigend sortierten Häufigkeiten danach ist p3 , p4 , . . . pn , p1 + p2 . Nach n/2 = 64 Schritten sieht
die Liste wie folgt aus p1 + p2 , p3 + p4 , . . . , pn−1 + pn . Man beachte, dass für diese
halb so lange Liste wieder gilt 2(p1 + p2 ) > (pn−1 + pn ) und man wiederholt das
Ganze. (Formal für Listen der Länge 2k mit Induktion über k.)
Herunterladen