Grundlagen der Programmierung 2 Aufgabenblatt Nr. 3 Aufgabe 1

Werbung
Prof. Dr. Manfred Schmidt-Schauß
Künstliche Intelligenz/Softwaretechnologie
Fachbereich Informatik und Mathematik/ Institut für Informatik
Goethe-Universität Frankfurt am Main
Grundlagen der Programmierung 2
Sommersemester 2017
Aufgabenblatt Nr. 3
Abgabe: Mittwoch 10. Mai 2017 vor! der Vorlesung
Aufgabe 1 (25 Punkte)
Verwenden Sie im Wesentlichen elem, head, tail, map, reverse, filter, concat, sum und (++),
um die folgenden Funktionen zur Listenverarbeitung in Haskell zu programmieren:
a) Eine Funktion, die einen String1 erhält und zunächst jedes Zeichen, das einer Ziffer entspricht, durch die Zahl 1 ersetzt und alle anderen Zeichen durch die Zahl 2, und danach
die Summe dieser Zahlen berechnet. Zum Beispiel soll für "123abc" der Wert 9 berechnet
werden.
(7 Punkte)
b) Eine Funktion, die eine Liste von Strings erhält und jedem String, der ein Fragezeichen
enthält, vorne den String F: anfügt. Zum Beispiel soll für ["1+1?","2.","ab?","c."]
das Ergebnis ["F:1+1?","2.","F:ab?","c."] berechnet werden.
(7 Punkte)
c) Eine Funktion, die eine Liste von Listen von Listen von Zahlen erhält und zunächst die
innersten Listen verschmilzt und die verschmolzenen Listen durch die Summen ihrer Elemente ersetzt. Anschließend sollen aus der eben erzeugten Liste alle Zahlen ≤ 20 entfernt
werden und die Reihenfolge der Elemente soll umgedreht werden. Zum Beispiel soll für
[[[1,2],[3,4]],[[5,6],[7,8]],[[10,11],[12,13]]] das Ergebnis [46,26] berechnet
werden.
(11 Punkte)
Hinweis: Die Bibliothek Data.Char beinhaltet die Funktion isNumber, die Sie in Ihrer Lösung
verwenden dürfen. Sie können die Bibliothek durch
import Data.Char
am Anfang des Quelltextes in Ihr Programm einbinden. Die Dokumentation von Bibliotheken
finden Sie im Internet unter http://www.haskell.org/ghc/docs/latest/html/libraries/.
Aufgabe 2 (30 Punkte)
Implementieren Sie in Haskell die folgenden Funktionen auf Listen im Wesentlichen unter Verwendung von Pattern-Matching und Rekursion.
a) Eine Funktion, die eine Liste von Listen entgegennimmt und eine Liste mit jeweils dem ersten Element der Listen berechnet. Zum Beispiel soll für die Eingabe
[[1,2,3],[4,5,6],[7,8,9]] das Ergebnis [1,4,7] berechnet werden.
(7 Punkte)
1
Strings sind in Haskell nichts anderes als Listen von Zeichen, d.h. "Haskell" ist nur eine andere Darstellung
für die Liste [’H’,’a’,’s’,’k’,’e’,’l’,’l’].
1
b) Eine Funktion, die einen String erwartet und die Summe aller im String vorkommenden
Ziffern berechnet. Zum Beispiel soll für die Eingabe "123a45" das Ergebnis 15 berechnet
werden.
(10 Punkte)
c) Eine Funktion, die eine Liste von Paaren erwartet, wobei das zweite Element eines jeden
Paares ein Tripel (i, j, k) ist, wobei die Werte der Tripel Zahlen sind. Zu berechnen ist
eine Liste, welche die Summe der jeweiligen Tripel aller geraden Listenelemente enthält.
Zum Beispiel soll für die Liste [(’A’,(9,6,3)), (’B’,(9,2,2)), (’C’,(19,1,2))] das
Ergebnis [13] berechnet werden.
(13 Punkte)
Aufgabe 3 (45 Punkte)
Diese Aufgabe beschäftigt sich mit Darts.
Das Dart-Board ist in 20 Zahlensegmente unterteilt. Die Felder zählen jeweils soviel, wie außen
am entsprechenden Segment notiert ist. Ausnahmen sind die schmalen Kreise. Im äußeren Kreis
zählen die Felder das Doppelte (Double-Felder), im mittleren Kreis das Dreifache (Triple-Felder)
der entsprechenden Zahl. Der Mittelpunkt des Boards, das Bullseye, zählt 50 Punkte (Double 25),
der Ring darum herum (Bull) 25 Punkte. Gespielt wird die Variante 501 mit Double-Out:
Jeder Spieler beginnt bei 501 Punkten. Eine Aufnahme besteht aus (maximal) drei nacheinander geworfenen Darts.
Die erzielten Punkte werden jedesmal von der verbleibenden Punktzahl abgezogen, wobei nach jeder Aufnahme der
jeweilige Gegenspieler dran ist. Es dürfen nur diejenigen
Darts gezählt werden, die im Board steckenbleiben. Gewonnen hat derjenige Spieler, der zuerst genau 0 Punkte
erreicht hat, wobei der letzte Dart ein Doppel-Feld oder
das Bullseye treffen muss. Erzielt der Spieler zu viele Punkte oder so viele, dass er nicht mehr mit einem Doppel abschließen kann (der Spieler überwirft sich), so werden alle
Darts dieser Aufnahme nicht gezählt – der Spieler bleibt auf
demselben Rest wie vor der Aufnahme. In der letzte Aufnahme, in der die Punktzahl genau auf 0 reduziert wird,
können auch weniger als 3 Darts geworfen werden. Falls
man sich überwirft kann eine Aufnahme ebenso aus weniger als 3 Darts bestehen.
5
20
einfach
1
12
18
9
4
14
13
11
6
8
10
dreifach
Bull
16
Bullseye
15
7
2
19
3
17
doppelt
Ein einzelnes Spiel dieser Art nennt man Leg. Wer zuerst eine festgelegte Anzahl an Legs gewonnen
hat, gewinnt das gesamte Spiel. Dabei beginnen die Spieler die Legs jeweils abwechselnd.
Für regelfeste Spieler: Die häufig eingesetzte Two-Clear-Legs-Regel wird aus Gründen der Einfachheit in dieser Aufgabe nicht angewendet.
Ein Darts-Spiel im obigen Modus sei in Haskell wie folgt dargestellt:
• Ein Paar (m, p) stellt die Punktzahl eines einzelnen geworfenen Darts dar, wobei für m
eine 1, 2 oder 3 entsprechend Single, Double oder Triple darstellt und p die Punktzahl
des Zahlensegments ist. Das heißt die Triple 20 entspricht der Darstellung (3, 20), Double
20 (2, 20) und Single 20 (1, 20). Da das Bullseye als Doppelfeld gezählt wird, wird es als
(2, 25) dargestellt. Außerdem entspricht (0, 0) einem Fehlwurf.
• Eine Aufnahme ist ein 3-Tupel solcher Paare, z.B. entspricht ((3, 20), (3, 19), (2, 25)) einem
Treffer in die Triple 20, gefolgt von einem Treffer in die Triple 19, gefolgt von einem Treffer
in das Bullseye.
2
• Ein Leg wird durch eine Liste solcher 3-Tupel dargestellt, in der jede Aufnahme mit ungerader Listenposition dem Spieler zugeordnet ist, der das Leg begonnen hat und alle geraden
dem Gegenspieler. Falls ein Spieler seine Aufnahme schon mit weniger als 3 Darts beendet
hat, sich also überworfen oder das Leg gewonnen hat, so wird das 3-Tupel mit (0, 0)-Würfen
aufgefüllt, z.B. ((2, 20), (0, 0), (0, 0)) wenn das Leg über die Double 20 gecheckt wird.
• Ein gesamtes Spiel ist ein Tupel bestehend aus 4 Komponenten:
1. Name des Spielers, der das erste Leg beginnt.
2. Name des Gegenspielers.
3. Die Anzahl der zum Sieg zu erreichenden Legs.
4. Liste von Legs.
Hier zwei Beispiel-Spiele zweier extrem starker Spieler:
leg1 = [((3,20),(3,20),(3,20)), ((3,20),(3,19),(2,25)), ((3,19),(3,19),(3,19)),
((3,20),(3,19),(2,25)), ((2,25),(2,25),(2,25))]
leg2 = [((3,20),(3,20),(3,20)), ((3,20),(3,19),(2,25)), ((3,19),(3,19),(3,19)),
((3,20),(3,19),(2,25)), ((2,25),(2,25),(1,25)), ((3,20),(3,19),(2,25))]
spiel1 = ("Tri-Bull", "Mr. Perfect", 6, [leg1,leg2,leg1,leg1,leg1,leg2,leg1])
spiel2 = ("Tri-Bull", "Mr. Perfect", 6, [leg1,leg2])
a) Implementieren Sie in Haskell eine Funktion legSieger, die ein Leg in der obigen Darstellung als Eingabe erwartet und True zurückliefert, falls der Spieler gewinnt, der das Leg
begonnen hat, andernfalls soll False zurückgegeben werden. Berücksichtigen Sie dazu die
oben dargestellten Regeln.
Die Funktion soll für fehlerhafte Legs eine entsprechende Fehlermeldung mithilfe der vordefinierten Funktion error ausgeben. Zum Beispiel falls kein Spieler die 0 Punkte erreicht
hat, die angegebenen Felder gar nicht existieren (zum Beispiel Triple-Bull oder Single-21)
oder falls ein Spieler bereits gewonnen hat und der Gegner danach trotzdem noch wirft.
Für die obigen Beispiel-Legs soll legSieger leg1 als Ergebnis True liefern und
legSieger leg2 soll False berechnen.
Tipp: Verwenden Sie Hilfsfunktionen um die Regeln systematisch abzudecken. Überlegen
Sie sich, wie man das Abwechseln der Spieler während des Legs einfach implementieren
kann.
(35 Punkte)
b) Implementieren Sie in Haskell eine Funktion spielErgebnis, die ein gesamtes Spiel in
obiger Darstellung entgegennimmt und einen String der Form "Name1 x:y Name2" ausgibt,
wobei x die Anzahl der gewonnen Legs des Spielers mit dem Namen Name1 und y die
Anzahl der gewonnen Legs des Spielers mit dem Namen Name2 ist. Die Funktion soll für
unvollständige Spiele eine entsprechende Fehlermeldung ausgeben.
Zum Beispiel soll spielErgebnis spiel1 das Ergebnis "Tri-Bull 6:1 Mr. Perfect"
zurückgeben, während spielErgebnis spiel2 eine Fehlermeldung liefern soll.
(10 Punkte)
3
Herunterladen