Grundlagen der funktionsorientierten Programmierung mit SCHEME/Würfeln mit mehreren Würfeln
Aus ProgrammingWiki
Wiki-Quelltext dieser Seite.
<language>Scheme</language>
<code id="4bd4971f736f1" hidden>
;-- M. Hielscher / Chr. Wagenknecht --
(define random-maker
(let* ((multiplier 48271)
(modulus 2147483647)
(apply-congruence
(lambda (current-seed)
(let ((candidate (modulo (* current-seed multiplier) modulus)))
(if (zero? candidate)
modulus
candidate))))
(coerce
(lambda (proposed-seed)
(if (integer? proposed-seed)
(- modulus (modulo proposed-seed modulus)) 19880214))))
(lambda (initial-seed)
(let ((seed (coerce initial-seed)))
(lambda args
(cond ((null? args)
(set! seed (apply-congruence seed))
(/ (- modulus seed) modulus))
((null? (cdr args))
(let* ((proposed-top
(ceiling (abs (car args))))
(exact-top
(if (inexact? proposed-top)
(inexact->exact proposed-top)
proposed-top))
(top
(if (zero? exact-top)
1
exact-top)))
(set! seed (apply-congruence seed))
(inexact->exact (floor (* top (/ seed modulus))))))
((eq? (cadr args) 'reset)
(set! seed (coerce (car args))))
(else
(display "random: unrecognized message")
(newline))))))))
(require-library 'sisc/libs/srfi/srfi-19)
(import srfi-19)
(define random (random-maker (time-nanosecond (current-time))))
</code>
[[Bild:Wuerfel1.jpg|miniatur|Wie wahrscheinlich ist es, mit 5 Würfeln die Augenzahl 15 zu werfen?]]
Wir wollen das gleichzeitige Werfen mehrerer Würfel simulieren. Dabei soll uns nur interessieren, ''wie oft'' die Summe aller Augenzahlen auftreten.<br />
Um signifikante Aussagen zu erhalten, muss diese Simulation in großer Anzahl wiederholt werden können.
== Lösungsidee ==
* Definiere eine Zählerliste, deren Startwerte Null sind.
* Die Position jedes Listenelements entspricht genau der Summe aller geworfenen Augenzahlen.
* Nach jedem Wurf wird die Summe aller Augenzahlen gebildet und der Wert des entsprechenden Listenelements um <math>1</math> erhöht.
* Wiederhole die Simulation in der gewünschten (großen) Anzahl.
== Implementation ==
<code id="4e7502f3c5964" hidden>
(define nr 1)
(define rand 50)
(define maxbreite (- 600 (* 2 rand)))
(define maxhoehe (- 400 (* 2 rand)))
(define canvas (eval (string->symbol (string-append "canvas" (number->string nr)))))
(define turtle (eval (string->symbol (string-append "turtle" (number->string nr)))))
(define minmax
(lambda (ls)
(letrec
([extremsuche
(lambda (extrem ls op)
(cond
[(null? ls) extrem]
[(op extrem (car ls)) (extremsuche (car ls) (cdr ls) op)]
[else
(extremsuche extrem (cdr ls) op)]))])
(cons (extremsuche 0 ls >)
(extremsuche 0 ls <)))))
(define balken
(lambda (hoehe breite)
(forward turtle breite) (left turtle 90)
(forward turtle hoehe) (left turtle 90)
(forward turtle breite) (left turtle 90)
(forward turtle hoehe) (left turtle 90)
(forward turtle breite)))
(define balkendiagramm
(lambda (ls)
(let* ([breite (/ maxbreite (length ls))]
[extremwerte (minmax ls)]
[min (car extremwerte)] [max (cdr extremwerte)])
(letrec
([zeichnen
(lambda (min max ls)
(if (null? ls)
'ok
(begin
(balken (round (* (/ (car ls) (- max min)) maxhoehe)) (round breite))
(zeichnen min max (cdr ls)))))])
(clear canvas)
(hide turtle)
(move turtle rand (+ rand (* (/ max (- max min)) maxhoehe))) (right turtle 90)
(zeichnen min max ls)))))
</code>
<code id="4e7b28cb14d18">
(define wuerfelzahl
(lambda ()
...))
(define wuerfeln
(lambda (wuerfel anz)
(letrec
([startliste
(lambda (pos)
(if (= pos 0)
()
(cons 0 (startliste (- pos 1)))))]
[summe
(lambda (wuerfel)
(if (= wuerfel 0)
0
(+ (wuerfelzahl) (summe (- wuerfel 1)))))]
[poszaehlen
(lambda (ls pos)
(if (= pos 1)
(cons (+ 1 (car ls)) (cdr ls))
(cons (car ls) (poszaehlen (cdr ls) (- pos 1)))))]
[zaehlen
(lambda (ls anz)
(if (= anz 0)
ls
(let ([pos (- (summe wuerfel) wuerfel -1)])
(zaehlen (poszaehlen ls pos) (- anz 1)))))])
(zaehlen (startliste (+ (* 5 wuerfel) 1)) anz))))
(define wuerfelausgabe
(lambda (wuerfel anz)
(letrec
([ausgabe
(lambda (ls pos)
(if (not (null? ls))
(begin
(display "Augenzahl ") (display pos) (display ":") (display #\tab) (display (car ls))
(newline)
(ausgabe (cdr ls) (+ pos 1)))))]
[maximum
(lambda (ls pos maxpos)
(if (null? (cdr ls))
(begin
(display "Die Augenzahl ") (display maxpos)
(display " ist mit der Anzahl ") (display (car ls)) (display " am häufigsten vertreten.")
(newline))
(if (> (car ls) (cadr ls))
(maximum (cons (car ls) (cddr ls)) (+ pos 1) maxpos)
(maximum (cdr ls) (+ pos 1) (+ pos 1)))))]
[ergebnis (wuerfeln wuerfel anz)])
(ausgabe ergebnis wuerfel)
(maximum ergebnis wuerfel wuerfel)
(balkendiagramm ergebnis)
'ok)))
</code>
<canvas w="600" h="400"></canvas>
<run id="4e7502f3c59e2">
(wuerfelausgabe 10 10000)
</run>
Zurück zur [[Grundlagen der funktionsorientierten Programmierung mit SCHEME/Sequenzielle Suche|Sequenziellen Suche]].