Praktische Informatik 3 WS 04/05
3. ¨ Ubungsblatt
Ausgabe: 29.11.04
Bearbeitungszeit: Zwei Wochen
Christoph L¨uth <cxl>
Shi Hui <shi>
Klaus L¨uttich <luettich>
Wolfgang Machert <wmachert>
Christian Maeder <maeder>
Hennes M¨artins<maertins>
Kai-Florian Richter <richter>
Dennis Walter <dw>
Diedrich Wolter <dwolter>
5 Advent, Advent. 6 Punkte
Jetzt ist wieder Adventszeit, und das beste daran (neben Gl¨uhwein) sind sicherlich die dazu- geh¨origen Kekse. Soziologen der University of Crumbles haben herausgefunden, dass es zwei Arten von Keksessern gibt: die einen m¨ogen ihre Kekssortimente ungeordnet, damit sie bei jedem Griff in die Packung einen anderen Keks zu fassen bekommen. Diese ¨Uberraschung erh¨oht f¨ur sie den Genuss. Solche Menschen sind impulsiv, risikofreudig, neigen aber etwas zum Leichtsinn; sie werden in ihrem sp¨ateren Leben zum Beispiel Torwart beim SV Werder.
Die andere Sorte Keksesser sortiert ihr Kekssortiment lieber nach verf¨ugbaren Sorten, damit sie ihre Lieblingssorte gut rationieren k¨onnen. Diese Menschen sind solide, risikobewusst, und neigen zu ¨Angstlichkeit und ¨Ubervorsicht; sie werden in ihrem sp¨ateren Leben zum Beispiel Verwaltungsfachangestellter der mittleren Laufbahn im ¨offentlichen Dienst.
In dieser Aufgabe geht es um die zweite Sorte Menschen. Es soll eine Funktion implemen- tiert werden, die ein Kekssortiment sortiert. Die verf¨ugbaren Kekssorten sind Zimtsterne, Spekulatius und Pfeffern¨usse. Modellieren Sie diese durch einen Aufz¨ahlungstyp Biscuit, und eine Dose voller Kekse als eine Liste von Keksen
data Box = Box [Biscuit]
Da es etwas unappetitlich w¨are, wild in den Keksen herumzuw¨uhlen, soll auf die Keksdose nur auf zwei Weisen zugegriffen werden k¨onnen: zum einen kann man sich anschauen, was f¨ur ein Keks an der Stelle i liegt, zum anderen kann man den Keks an der i-ten Stelle mit dem i+1-ten Keks vertauschen. Dieses wird durch zwei Funktionen implementiert, eine dritte gibt die Anzahl der Kekse in der Dose an:
look :: Box-> Int-> Biscuit swap :: Box-> Int-> Box num :: Box-> Int
Mit Hilfe genau dieser drei Funktionen (keine anderen Zugriffe auf Box) implementieren Sie jetzt eine Funktion, die eine beliebige Keksdose so sortiert, dass die Zimtsterne vorne liegen, gefolgt von den Gew¨urzspekulatius, und die Pfeffern¨usse dahinter.
1
6 Dot-Com zum letzten 6 Punkte
Der Internetboom ist ja jetzt schon seit einigen Jahren vor¨uber, und den Kater danach haben wir auch ¨uberstanden. Inzwischen gibt es wieder leicht zu t¨auschende, ¨ah, risikofreudigeven- ture capitalists, die anderer Leute sauer verdientes Geld gerne f¨ur alles ausgeben, was einen Punkt im Namen tr¨agt. Sie wollen von dieser neuerlichen Phantasmagorie profitieren, und gr¨unden eine kleine Firma. Ihr Marktvorteil ist die Verwendung einer Computersprache der neuen Generation, so jedenfalls erz¨ahlen Sie ihrem Bankberater, die ungeahnte Produktivit¨at und Codequalit¨at erm¨oglicht. Sie ahnen es schon — diese Sprache ist Haskell.
In dieser Aufgabe werden wir also eine text rendering engine f¨ur effizientescontent manage- ment implementieren. Dieses soll Dokumente an Hand einer Vorlage formatieren, und dann im Internet darstellen.
Ein Dokument besteht aus einem Titel und einer Folge von Textabschnitten. Ein Textab- schnitt besteht aus
• einer ¨Uberschrift und einer Folge von Textabschnitten, oder
• einem Absatz.
EinAbsatz besteht aus
• einer Folge von Texten (Zeichenketten), die jeweils hervorgehoben sein k¨onnen, oder
• aus einer Aufz¨ahlung von Abs¨atzen.
Ein formatierter Text korrespondiert direkt zur Formatierung in der im Internet verbrei- teten Hypertext Markup Language (HTML), und besteht aus einer Folge von formatier- ten Textelementen. Ein formatiertes Textelement (zusammen mit den dargestellten HTML- Formatierungselementen) ist
• ein St¨uck einfacher Text;
• ein St¨uck fettgedruckter Text (<b>. . .</b>);
• ein St¨uck kursiver Text (<i>. . .</i>);
• eine Aufz¨ahlung von formatierten Texten mit Spiegelstrichen oder numeriert (<ul><li>. . .<li>. . .</ul>, <ol><li>. . .<li>. . .</ol>);
• eine ¨Uberschrift, Unter¨uberschrift, Unterunter¨uberschrift oder Unterunterunter¨uber- schrift (<h1>. . .</h1> bis<h4>. . .</h4>).
EineTextvorlage besteht aus einem Kopf und einem Fuß, die beliebiger formatierter Text sind und jedem Dokument voran- bzw. hintenangestellt werden, sowie einer Formatierungsvor- schrift, die angibt, ob Hervorhebung durch Fett- oder Kursivschrift erfolgt, und ob Aufz¨ahlun- gen durch Spiegelstriche oder numeriert erfolgen sollen.
Implementieren Sie Datentypen Document, FText und Template f¨ur Dokumente, forma- tierten Text und Textvorlage. Implementieren Sie eine Funktion, die ein Dokument unter Verwendung einer Textvorlage in einen formatierten Text umwandelt:
format :: Document-> Template-> FText
Der Titel des Dokumentes sollte als ¨Uberschrift formatiert werden, und die ¨Uberschriften verschachtelter Textabschnitte absteigend als Untern¨uberschriften (mit 1≤n≤3).
Implementieren Sie ferner eine Funktion, welche formatierten Text in ein HTML-Dokument umwandelt:
render :: FText -> String
Hinweis: Ziel dieser Aufgabe ist die m¨oglichst getreue Modellierung der Datentypen, nicht die Darstellung von m¨oglichst ausgefallenem HTML.
7 Eins, Zwei, Drei. 8 Punkte
Der Spielemarkt boomt, und wir wollen uns ein St¨uck des Kuchens abschneiden. Um nicht in Konflikt mit investigativen Fernsehnachrichtenmagazinen und der Freiwilligen Selbstkon- trolle zu geraten, nehmen wir allerdings an dieser Stelle Abstand von der Implementierung von Doom IV und widmen uns einem harmloseren Spiel, welches im englischen Sprachraum als Tic-Tac-Toe bekannt ist.
Dieses Spiel wird von zwei Spielern (Xund O) gespielt, die auf einem 3×3-Feld abwechselnd Spielsteine auf nichtbesetzte Felder setzen. Wer zuerst drei Steine in einer Reihe, Zeile oder Diagonalen gesetzt hat, hat gewonnen; wenn das Feld voll ist, ohne dass ein Spieler gewonnen hat, ist das Spiel unentschieden.
Wir modellieren Spieler durch einen Aufz¨ahlungstyp Player, und den Spielbrettzustand als Datentyp Board. Der Spielbrettzustand ist eine 3×3-Matrix, bei der an jeder Stelle (i, j) entweder einer der beiden Spieler einen Stein plaziert hat, oder die Stelle ist leer.
Ein einzelner Zug ist ein Paar (i, j) mit 1≤i, j ≤3. Wir wollen eine Funktion type Move = (Int, Int)
move :: Board-> Player-> Result
implementieren, die bei einem Spielbrettzustand f¨ur den Spieler den n¨achsten bestm¨oglichen Zug berechnet. Der DatentypResultmodelliert das Ergebnis: einen gewinnenden Zug, wenn es einen solchen gibt; ansonsten ein zumindest nicht verlierender Zug, wenn es einen solchen gibt; ansonsten Aufgabe. Vorbedingung f¨ur move ist, dass ¨uberhaupt noch ein Zug m¨oglich ist, d.h. das Brett ist noch nicht voll.
Um einen gewinnenden Zug zu berechnen, pr¨ufen wir alle m¨oglichen Z¨uge, ob sie gewinnen.
Ein Spieler gewinnt, wenn er direkt in einer Gewinnsituation ist, oder dem Gegner nur Z¨uge l¨aßt, in denen dieser verliert. Ein Spieler verliert, wenn er nicht in einer Gewinnsituation ist, und der Gegner mindestens einen gewinnenden Zug machen kann. (Der Kenner ersp¨aht die Rekursion). Um den Suchraum einzuschr¨anken, reduzieren wir alle m¨oglichen Z¨uge auf die nicht durch Rotation oder Spiegelung ineinander ¨uberf¨uhrbaren.
Dies ist Version 1.1 vom 2004/12/03 14:21:41.