Grundlagen der funktionsorientierten Programmierung mit SCHEME/Primzahlfilter

Aus ProgrammingWiki

Wiki-Quelltext dieser Seite.

<language>Scheme</language>
<code id="4bd496d2acb43" 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>

Zunächst soll unser Filter an einer generierten Liste natürlicher Zahlen getestet werden:

<code id="4e74bfb04b223">
(define natzahlliste
  (lambda (n)
    (if (= n 0)
        (list 0)
        (append (natzahlliste (- n 1)) (list n)))))

(define ungerade?
  (lambda (n)
    (= (modulo n 2) 1)))

(define my-filter
  (lambda (proz ls)
    ...))
</code>

<check>
(and (equal? (my-filter ungerade? '(1 2 3 4 5) '(1 3 5)) (my-filter ungerade? '(2 4 6 8 10) '())))
</check>

<run id="4b1118006b030">
(my-filter ungerade? (natzahlliste 50))
</run>

In einer ersten Idee müsste der Primzahlprüfer die Teilbarkeit der Zahl <math>n</math> durch alle Vorgänger prüfen und als Teiler nur die <math>1</math> finden.<br />
Nach weiterführenden Überlegungen kann die Suche aber auf ungerade Teiler bis <math>\sqrt{n}</math> beschränkt werden:
<code id="4b1118006a099">
(define primzahl?
  (lambda (n)
    (letrec
        ([prim?
          (lambda (n t)
            (cond
              [(> t (sqrt n)) #t]  
              [(= (modulo n t) 0) #f]                  
              [else
               (prim? n (+ t 2))]))])
      (cond
        [(= n 2) #t]
        [(or (< n 2) (= (modulo n 2) 0)) #f]
        [else        
         (prim? n 3)]))))
</code>

'''Hinweis:''' Mit <tt>letrec</tt> lassen sich ''lokale rekursive'' Datenstrukturen definieren.

<run id="4b112117825f1">
(my-filter primzahl? (natzahlliste 100))
</run>

Interessante Untersuchungen lassen sich an Listen mit ''zufälligen'' natürlichen Zahlen vornehmen:

<code id="4b112718adfd2">
(define zufallsliste
  (lambda (bis n)
    (if (= n 0)
        ()
        (cons (+ 1 (random bis)) (zufallsliste bis (- n 1))))))
</code> 

<run id="4b112718aef77">
(my-filter primzahl? (zufallsliste 1000 100))
</run>

Zurück zu [[Grundlagen der funktionsorientierten Programmierung mit SCHEME/Prozeduren höherer Ordnung (I)|Prozeduren höherer Ordnung (I)]].