P1-WS04-MusterLoesung11.txt

Aus Fachschaft_Informatik
Version vom 5. November 2007, 06:50 Uhr von PatrickFey (Diskussion | Beiträge) (2 Versionen)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen
; 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 (wert[[VonBetrag]] betrag)    
	 (car betrag))

;(define (waehrung[[VonBetrag]] betrag) 
;	(car (cdr betrag)))
; bzw. kuerzer

(define (waehrung[[VonBetrag]] betrag)
	 (cadr betrag))
    
;;; Test
;   > (wert[[VonBetrag]] (neuerGeldbetrag 2 'Euro))
;    2
;    > (waehrung[[VonBetrag]] (neuerGeldbetrag 2 'Euro))
;    euro
    
;;;(c) 

(define (nachEuro betrag)
      (case  (waehrung[[VonBetrag]] betrag) 
        
            ; ist schon Euro => keine Aenderung
            ((euro) betrag)
            ; Konvertierung von Dollar
            ((dollar) 
                   (neuerGeldbetrag (/  (wert[[VonBetrag]] betrag) [[EURO2DOLLAR]]) 'Euro))
            ; Konvertierung von Pfund
            ((pounds) 
                   (neuerGeldbetrag (/ (wert[[VonBetrag]] betrag) [[EURO2PFUND]]) 'Euro))
            ; falsche Waehrung => false
            (else #f)))

    (define (vonEuro betrag waehrung)
      (cond 
            ; falsche Quellwaehrung => false
            ((not (eq? (waehrung[[VonBetrag]] betrag) 'euro)) #f)
            ; Euro nach Euro
            ((eq? waehrung 'euro) betrag)
            ; Euro nach Dollar
            ((eq? waehrung 'dollar) 
                (neuerGeldbetrag (* (wert[[VonBetrag]] betrag) [[EURO2DOLLAR]]) 'Dollar))
            ; Euro nach Pfund
            ((eq? waehrung 'pounds) 
                (neuerGeldbetrag (* (wert[[VonBetrag]] 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 (addiere[[WaehrungsgleicheBetraege]] betrag1 betrag2)
  (let* (
         (wert1 (wert[[VonBetrag]] betrag1))
         (wert2 (wert[[VonBetrag]] betrag2))
         (waehrung (waehrung[[VonBetrag]] betrag1))
         (summe (+ wert1 wert2))
         )
    (neuerGeldbetrag summe waehrung)))

;;; Test
; > (addiere[[WaehrungsgleicheBetraege]] (neuerGeldbetrag 2 'Euro) (neuerGeldbetrag 4 'Euro))
; (6 euro)
 

;;; e) 

(define (addiere betrag1 betrag2)
  (let* (
         ; Konvertiere Betraege nach Euro und ...
         (neuer[[GeldbetragInEuro1]] (nachEuro betrag1))
         (neuer[[GeldbetragInEuro2]] (nachEuro betrag2))
         )
    ; ... addiere mit addiere[[WaehrungsgleicheBetraege]]
    (addiere[[WaehrungsgleicheBetraege]] neuer[[GeldbetragInEuro1]] neuer[[GeldbetragInEuro2]])))
  

    
;;; 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 gewŠhlte 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)