P1-WS04-MusterLoesung11.txt: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
fsrwiki_>1illig K (antispam) |
(kein Unterschied)
|
Version vom 22. Dezember 2006, 07:47 Uhr
; Muesterloesung Aufgabenblatt 11 ; P1 WiSe 04/05 ; Oezguer Oezcep ;;; Aufgabe 1 (Abstrakter Datentyp) ;;; ------------------------------ ;;; Umrechnungskurs (define EURO2DOLLAR 1.32) (define EURO2PFUND 0.70) ;;; (a) (define (neuerGeldbetrag wert waehrung) (list wert waehrung)) ;;; Test ; > (neuerGeldbetrag 2 'Euro) ; (2 euro) ;;;(b) (define (wertVonBetrag betrag) (car betrag)) ;(define (waehrungVonBetrag betrag) ; (car (cdr betrag))) ; bzw. kuerzer (define (waehrungVonBetrag betrag) (cadr betrag)) ;;; Test ; > (wertVonBetrag (neuerGeldbetrag 2 'Euro)) ; 2 ; > (waehrungVonBetrag (neuerGeldbetrag 2 'Euro)) ; euro ;;;(c) (define (nachEuro betrag) (case (waehrungVonBetrag betrag) ; ist schon Euro => keine Aenderung ((euro) betrag) ; Konvertierung von Dollar ((dollar) (neuerGeldbetrag (/ (wertVonBetrag betrag) EURO2DOLLAR) 'Euro)) ; Konvertierung von Pfund ((pounds) (neuerGeldbetrag (/ (wertVonBetrag betrag) EURO2PFUND) 'Euro)) ; falsche Waehrung => false (else #f))) (define (vonEuro betrag waehrung) (cond ; falsche Quellwaehrung => false ((not (eq? (waehrungVonBetrag betrag) 'euro)) #f) ; Euro nach Euro ((eq? waehrung 'euro) betrag) ; Euro nach Dollar ((eq? waehrung 'dollar) (neuerGeldbetrag (* (wertVonBetrag betrag) EURO2DOLLAR) 'Dollar)) ; Euro nach Pfund ((eq? waehrung 'pounds) (neuerGeldbetrag (* (wertVonBetrag betrag) EURO2PFUND) 'Pounds)) ; falsche Zielwaehrung => false (else #f))) ;;; Test ; Wir testen, dass Hin- und Rueckkonvertierung wieder den originalen Betrag ; ergibt ; > (nachEuro (vonEuro (neuerGeldbetrag 2 'Euro) 'Euro)) ; (2 euro) ; > (nachEuro (vonEuro (neuerGeldbetrag 2 'Euro) 'Dollar)) ; (2.0 euro) ; > (nachEuro (vonEuro (neuerGeldbetrag 2 'Euro) 'Pounds)) ; (2.0 euro) ;;; d) ;;; Vorbedingung: die Waehrungen von betrag1 und betrag2 sind gleich (define (addiereWaehrungsgleicheBetraege betrag1 betrag2) (let* ( (wert1 (wertVonBetrag betrag1)) (wert2 (wertVonBetrag betrag2)) (waehrung (waehrungVonBetrag betrag1)) (summe (+ wert1 wert2)) ) (neuerGeldbetrag summe waehrung))) ;;; Test ; > (addiereWaehrungsgleicheBetraege (neuerGeldbetrag 2 'Euro) (neuerGeldbetrag 4 'Euro)) ; (6 euro) ;;; e) (define (addiere betrag1 betrag2) (let* ( ; Konvertiere Betraege nach Euro und ... (neuerGeldbetragInEuro1 (nachEuro betrag1)) (neuerGeldbetragInEuro2 (nachEuro betrag2)) ) ; ... addiere mit addiereWaehrungsgleicheBetraege (addiereWaehrungsgleicheBetraege neuerGeldbetragInEuro1 neuerGeldbetragInEuro2))) ;;; Test ; > (addiere (neuerGeldbetrag 2 'Euro) (neuerGeldbetrag 2 'Euro)) ; (4 euro) ; > (addiere (neuerGeldbetrag 2 'Euro) (neuerGeldbetrag 2 'Dollar)) ; (3.515151515151515 euro) ; > (addiere (neuerGeldbetrag 2 'Dollar) (neuerGeldbetrag 2 'Euro)) ; (3.515151515151515 euro) ; > (addiere (neuerGeldbetrag 2 'Dollar) (neuerGeldbetrag 2 'Dollar)) ; (3.0303030303030303 euro) ;;; Aufgabe 2 (Teilstuecke einer Liste) ;;; ----------------------------------- ;;; a) ; Zunaechst eine Loesung ohne Fehlerbehandlung. Die Idee: Falls die Tiefe noch ; groesser ist als 0, besteht die Loesung aus dem Kopf und den ersten n-1 Elementen ; des Schwanzes: (define (take n liste) (cond ((= n 0) '()) (else (cons (car liste) (take (- n 1) (cdr liste)))))) ; Zwei Reaktionen bei zu hohem n koennen als sinnvoll angesehen werden: ; 1) Ausgabe eines Fehlers ; 2) Rueckgabe der gesamten Liste ; Die Loeung fuer Variante 1) laesst sich z.B. durch eine Wrapper- ; Funktion realisieren, welche take nur aufruft, falls n <= (length liste): (define (w_take n liste) (if (<= n (length liste)) (take n liste) (error "n ist groesser als die Listenlaenge"))) ;;; Test: ;> (w_take 1 '(1 2 3)) ;(1) ;> (w_take 2 '(1 2 3)) ;(1 2) ;> (w_take 4 '(1 2 3)) ; n ist groesser als die Listenlaenge ;> (w_take 4 '(1 2 3)) ; Die Loesung fuer Variante 2) erreicht man, indem nicht nur das Erreichen von ; n=0 zum Rekursionsabbruch fuehrt, sondern auch (null? list) : (define (take n liste) (cond ((= n 0) '()) ((null? liste) ; <-- '()) ; <-- (else (cons (car liste) (take (- n 1) (cdr liste)))))) ;;; Test: ;> (take 4 '(1 2 3)) ;(1 2 3) ;;;(b) ; Zunaechst wieder die Loesung ohne Fehlerbehandlung. (define (drop n liste) (cond ((= n 0) liste) (else (drop (- n 1) (cdr liste))))) ; Abgefangen muss hier der Fall werden, dass mehr Elemente abgeschnitten ; werden sollen als die Liste Elemente hat. Analog sind wieder 2 Reaktionen ; moeglich: ; 1) Ausgabe eines Fehlers ; 2) Rueckgabe der leeren Liste ; Die Loesung fuer Variante 1) analog zu a): (define (w_drop n liste) (if (<= n (length liste)) (drop n liste) (error "n ist zu gross"))) ;;;; Test: ;> (w_drop 1 '(1 2 3)) ;(2 3) ;> (w_drop 0 '(1 2 3)) ;(1 2 3) ;> (w_drop 2 '(1 2 3)) ;(3) ;> (w_drop 4 '(1 2 3)) ; n ist zu gross ; Und auch bei 2) koennen wir uns an a) orientieren: Falls (null? liste) ist, ; gib die leere Liste zurueck. (define (drop n liste) (cond ((= n 0) liste) ((null? liste) ; <-- '()) ; <-- (else (drop (- n 1) (cdr liste))))) ;;;Test: ;> (drop 4 '(1 2 3)) ;() ;;; c) ; Anders formuliert: (subseq start stop liste) bewirkt, dass von den ersten ; 'stop' Elementen von 'liste' die ersten 'start' Elemente abgeschnitten werden: (define (subseq start stop liste) (drop start (take (+ stop 1) liste))) ; Das (+ stop 1) ergibt sich dabei aus der Tatsache, dass take die ersten n ; Elemente der Liste bestimmt, also z.b. 4 Elemente, welche aber fuer subseq ; mit den werten 0-3 nummeriert sind. Aus eben diesem Grund muss auch start ; nicht veraendert werden, denn dadurch dass bei 0 angefangen wird zu zaehlen ; enthaelt start schon genau die Anzahl an Elementen, die entfernt werden muessen ;;; Test ;> (subseq 0 0 '(1 2 3)) ;(1) ;> (subseq 0 1 '(1 2 3)) ;(1 2) ;> (subseq 0 2 '(1 2 3)) ;(1 2 3) ;> (subseq 0 3 '(1 2 3)) ;(1 2 3) ;> (subseq 1 2 '(1 2 3)) ;(2 3) ;> (subseq 3 0 '(1 2 3)) ;() ;;; Aufgabe 3 (Gute Vorsaetze) ;;;--------------------------- ;;; Hilfsfunktionen von Dreschler-Fischer's tools.scm ;;;; ========================================================= ;;;; random numbers ;;;; ========================================================= (define *last-ran* 1) ; the previous random number (define (random-real) ;;; pick a random real number between 0 and 1.0 (let* ((a (add1 (expt 2 7))) (b 1) (T (sub1 (expt 2 35))) (next-ran (remainder (+ (* a *last-ran*) b) T))) (set! *last-ran* next-ran) (/ next-ran T))) (define (random n) ;;; pick a random integer between 0 and n-1 (floor (* n (random-real)))) (define (random-elt choices) ;;; Choose an element from a list at random (list-ref choices (random (length choices)))) ;;; ---------------------------------------------- ;;; Die Hilfsfunktion one-of (Skript S. 107) in etwas variierter Form ;;; Das zufaellig aus der Liste set gewhlte Element wird nur in dem Fall, ;;; dass es keine Liste ist, in eine Liste eingebettet. (define (one-of set) (let ((element (random-elt set))) (if (list? element) element (list element)))) ;;; a) ;Es werden zur Loesung der Aufgabe nur solche Vorsaetze betrachtet, die sich in der ; Form <Skalar> <Verbalphrase> wiedergeben lassen. ;Da nach "guten" Vorsaetzen gefragt ist, ist die Kombination der Skalare mit den ;Verbalphrasen zu beachten; z.B. ist (weniger rauchen) ein guter Vorsatz, hingegen ;(mehr rauchen) nicht. ; ;In der Grammatik muessen folglich "positive" und "negative" Verbalphrasen sowie ;+Skalare ("mehr", haeufiger") und -Sklarae ("weniger", "seltener") unterschieden ;werden. Ein guter Vorsatz sollte einer sein, der mehr an positiven Taten oder ;weniger an negativen Taten verlangt. ; ; ; ;Grammatik ; ;(1) <+Skalar> ::= mehr | fleissiger | haeufiger ;(2) <-Skalar> ::= weniger | seltener ;(3) <positiveVerbalphrase> ::= sparen | lernen | lesen | Sport treiben ;(4) <negativeVerbalphrase>::= trinken | Auto fahren | rauchen ;(5) <guterVorsatz> ::= <+Skalar><positiveVerbalphrase> ;(6) <guterVorsatz> ::= <-Skalar><negativeVerbalphrase> ;;; b) ; Regeln der (einfachen) Grammatik als Scheme-Code (define (guterVorsatz) ; waehlt zufaellig einen der beiden Faelle ( (5) oder (6) ) ; fuer guete Vorsaetze aus (random-elt (list (append (-Skalar) (negativeVerbalphrase)) (append (+Skalar) (positiveVerbalphrase))))) (define (negativeVerbalphrase) (one-of (list 'trinken (list 'Auto 'fahren) 'rauchen))) (define (positiveVerbalphrase) (one-of (list 'sparen 'lernen (list 'Sport 'treiben) 'lesen))) (define (+Skalar) (one-of '(mehr fleissiger haeufiger))) (define (-Skalar) (one-of '(weniger seltener))) ;;;; Test ;> (guterVorsatz) ;(haeufiger lesen) ;> (guterVorsatz) ;(fleissiger lernen) ;> (guterVorsatz) ;(weniger auto fahren) ;> (guterVorsatz) ;(seltener rauchen) ;> (guterVorsatz) ;(weniger auto fahren) ;> (guterVorsatz) ;(fleissiger lesen) ;> (guterVorsatz) ;(haeufiger lesen) ;> (guterVorsatz) ;(fleissiger sport treiben) ;> (guterVorsatz) ;(weniger trinken) ;> (guterVorsatz) ;(weniger auto fahren) ;> (guterVorsatz) ;(weniger trinken) ;> (guterVorsatz) ;(mehr sparen) ;> (guterVorsatz) ;(mehr sport treiben) ;> (guterVorsatz) ;(mehr sport treiben) ;> (guterVorsatz) ;(mehr sport treiben) ;> (guterVorsatz) ;(weniger auto fahren) ;> (guterVorsatz) ;(haeufiger lernen) ;> (guterVorsatz) ;(seltener trinken) ;> (guterVorsatz) ;(seltener rauchen) ;> (guterVorsatz) ;(weniger rauchen)