Aufgabe 7.1/7.2

Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.

Aufgabe 7.1/7.2
Ziemlich viel Code und eigentlich eher unelegant. Vielleicht bekommt das ja jemand noch schöner hin?

[CODE](define (1+ x) (+ 1 x))

(define (divides? n1 n2) (zero? (remainder n1 n2)))

; findet heraus, ob ein Jahr ein Schaltjahr ist.
(define (schaltjahr? jahr)
(or (and (divides? jahr 4) (not (divides? jahr 100)))
(divides? jahr 400)))

; berechnet, wie viele Tage ein Jahr hat.
(define (jahrestage jahr)
(if (schaltjahr? jahr) 366 365))

; berechnet, wie viele Tage ein Monat hat.
(define (monatstage monat jahr)
(cond ((eq? monat 2) (if (schaltjahr? jahr) 29 28))
((<= monat 7) (if (even? monat) 30 31))
(else (if (odd? monat) 30 31))))

; berechnet, am wievielten Tag im Jahr wir uns befinden.
(define (tag_des_jahres tag monat jahr)
(do ((tsum 0 (+ tsum (monatstage m jahr))) (m 1 (1+ m)))
((eq? m monat) (+ tsum tag)) ()))

(define (lebenstage th mh jh tg mg jg)
(let ((tdjh (tag_des_jahres th mh jh))
(tdjg (tag_des_jahres tg mg jg)))
(if (eq? jh jg)
(- tdjh tdjg)
(do ((j (1+ jg) (1+ j))
(tsum (- (jahrestage jg) tdjg) (+ tsum (jahrestage j))))
((eq? j jh) (+ tsum tdjh))
()))))[/CODE]


Nicht wirklich schöner, man kann sich sicher den ein oder anderen Teil sparen, wenn man das ganze optimieren will. Hat mir nu aber schon lange genug gedauert :-p :-p

[code](define (lebenstage gt gm gj ht hm hj)
(define (schaltjahr jahr)
(if (AND (= (modulo jahr 4) 0) (eqv? (= (modulo jahr 100) 0) (= (modulo jahr 400) 0)))
#t
#f))

(define (TagEinesJahres tag monat jahr)
(define (Schleife ct cm counter)
(if (AND (> cm 0) (< cm 13))
(cond ((AND (< cm :cool: (= (modulo cm 2) 0)) (Schleife 31 (- cm 1) (+ counter ct)))
((AND (< cm :cool: (= (modulo cm 2) 1)) (Schleife 30 (- cm 1) (+ counter ct)))
((= cm :cool: (Schleife 31 (- cm 1) (+ counter ct)))
((AND (> cm :cool: (= (modulo cm 2) 0)) (Schleife 30 (- cm 1) (+ counter ct)))
((AND (> cm :cool: (= (modulo cm 2) 1)) (Schleife 31 (- cm 1) (+ counter ct))))
counter))

(cond ((AND (> monat 2) (schaltjahr jahr)) (- (Schleife tag monat 0) 1))
      ((AND (> monat 2) (NOT (schaltjahr jahr))) (- (Schleife tag monat 0) 2))
      (else (Schleife tag monat 0))))

(define (Durchzählen cj counter)
(cond ((= cj hj) (Durchzählen (+ cj 1) (+ counter (TagEinesJahres ht hm hj))))
((= cj gj) (Durchzählen (+ cj 1) (+ counter (- (TagEinesJahres 31 12 cj) (TagEinesJahres gt gm gj)) 1)))
((> cj hj) counter)
(else (Durchzählen (+ cj 1) (+ counter (TagEinesJahres 31 12 cj))))))

(Durchzählen gj 0))[/code]


Also meine Version beinhaltet nur schon benutzte Befehle, und is noch ein bisschen kürzer als eure :smiley:
Ich laufe vom ursprünglichen Datum bis zum jetzigen in Tagesschritten vorwärts, und überprüfe ob der jeweilige Tag der letzte des jeweiligen Monats ist. Wenn ja, dann spring ich zum nächsten Monat (oder Jahr).
Z.B: [list]
iter (tage tag monat jahr)
iter (1 27 2 2000)
iter (2 28 2 2000)
iter (3 29 2 2000)
iter (4 1 3 2000)
iter (5 2 3 2000)

[/list]

[CODE]; teilt b a?
; Beispiel: divides? (4 16) ergibt #t

(define divides? (lambda (b a)
(zero? (remainder a b))))

; Ist jahr ein Schaltjahr?
(define schaltjahr? (lambda (jahr)
(or (and (divides? 4 jahr) (not (divides? 100 jahr)))
(divides? 400 jahr))))

; Gibt die Anzahl der Tage im Monat monat des Jahres jahr zurück
; Beispiel: (monatstage 2 2000) → 20

(define monatstage (lambda (monat jahr)
(cond ((or (and (< monat :cool: (odd? monat)) (and (> monat 7) (even? monat))) 31)
((= monat 2) (if (schaltjahr? jahr) 29 28))
(else 30))))

; gibt die Anzahl der Tage von tag monat jahr bis tag_jetzt monat_jetzt jahr_jetzt zurück
; Beispiel (lebenstage 1 1 2000 1 3 2000) 61
; (lebenstage 1 1 2001 31 21 2002) 730

(define lebenstage (lambda (tag monat jahr tag_jetzt monat_jetzt jahr_jetzt)
(define iter (lambda (tage tag monat jahr)
(if (and (= tag tag_jetzt) (= monat monat_jetzt) (= jahr jahr_jetzt)) tage
(cond ((= tag (monatstage monat jahr)) (if (= monat 12)
(iter (+ tage 1) 1 (- monat 11) (+ jahr 1))
(iter (+ tage 1) 1 (+ monat 1) jahr)))
(else (iter (+ tage 1) (+ tag 1) monat jahr))))))

(iter 1 tag monat jahr)))

[/CODE]


Meine Lösung ist so ähnlich wie die von Krull, aber anstatt der do-Schleifen verwende ich eine Endrekursion in der Prozedur summe:

[CODE];schaltjahr-praedikat
(define (schaltjahr jahr)
(cond ((= 0 (modulo jahr 400)) #t)
((= 0 (modulo jahr 100)) #f)
((= 0 (modulo jahr 4)) #t)
(else #f)))

;berechnet die anzahl der tage eines jahres
(define (days-of-year year)
(if (schaltjahr year) 366 365))

;erzeugt einen lambda-ausdruck, der die monatstage eines bestimmten jahres berechnet
(define (days-of-mounth year)
(lambda (mounth)
(case mounth
((1 3 5 7 8 10 12) 31)
((4 6 9 11) 30)
((2) (if (schaltjahr year) 29 28))
(else (begin (display "error: invalid mounth: ")
(display mounth)
(newline))))))

;berechnet die summe der terme t(a) bis t(b)
(define (summe term a b)
(define (sum-loop c s)
(if (> c b)
s
(sum-loop (+ c 1) (+ s (term c)))))
(sum-loop a 0))

(define (lebenstage g_tag g_monat g_jahr tag monat jahr)
(- (+ (summe days-of-year g_jahr (- jahr 1))
(summe (days-of-mounth jahr) 1 (- monat 1))
tag
1)
(+ (summe (days-of-mounth g_jahr) 1 (- g_monat 1))
g_tag)))

(lebenstage 17 3 1979 1 8 2006)[/CODE]


Kurz ist es schon, nur laufen tut es (zumindest bei mir) nicht. Ich hab jetzt keinen Nerv mir das durchzusehen, aber zumindest in monatstage fehlen zwei Klammern am Ende, aber da scheint noch mehr schief zu laufen, weil auch mit den Klammern geht es nicht.

Gruss
Swarsron


So, mal ne iterative Version

(define (schaltjahr? jahr)
    (if (> (modulo jahr 4) 0)
        #f
        (if (= (modulo jahr 100) 0)
            (if (= (modulo jahr 400) 0)
                #t
                #f)
            #t)))

(define (monat_tag monat)
    (case monat 
        ((1 3 5 7 8 10 0) 31)
        ((2) 28)
        ((4 6 9 11) 30)))

(define (lt t m j gt gm gj)
    (if (> (- j gj) 0)
        (if (schaltjahr? j)
            (lt (+ t 1) (+ m 12) (- j 1) gt gm gj)
            (lt t (+ m 12) (- j 1) gt gm gj))
        (if (> m gm)
            (lt (+ t (monat_tag (modulo m 12))) (- m 1) j gt gm gj)
            (+ (- t gt) 1))))

Hmm, meine Variante is aber auch iterativ. Also kein Monopol beanspruchen :wink:


Hmm, bei mir läufts einwandfrei, der (Code) Befehl fügt Leerzeichen ein, wo eigentlich gar keine sein sollten.
Ausserdem hab ich in der Übung gesehen, dass meine Version viel zu viel Zeit braucht, die Jahre dazwischen kann man auch einfach zusammenfassen.