Prozeduren höherer Ordnung-Loesung

Aus ProgrammingWiki

Wiki-Quelltext dieser Seite.

<language>Scheme</language>
[[Programmierparadigmen_-_Computerübungen|zur Übungsübersicht]]

<code id="4af43622f15f4" hidden>
(define listvergleich
 (lambda(l1 l2)
  (cond
   ((and (null? l1) (null? l2)) #t)
   ((not (= (length l1) (length l2))) #f)
   ((not (= (car l1) (car l2) )) #f)
   (else (listvergleich (cdr l1) (cdr l2)))
  )
 )
)
(define groesser
  (lambda (w)
     (> w 0)))
</code>


==Filter==
Schreiben Sie eine Prozedur <tt>filter</tt>, die eine Liste und eine Filterprozedur nimmt, und eine "gefilterte" Liste zurückgibt.

'''Hinweis:''' Die Filterprozedur ist eine einstellige Prozedur, welche <tt>#t</tt> bzw. <tt>#f</tt> zurückgibt.

'''Aufrufbeispiele'''
 >(filter '(1 2 3 4 5 6 7 8 9) even?)
 (2 4 6 8)
 >(filter '(1 2 3 4 5) (lambda (x) (not (or (= x 2) (= x 5)))))
 (1 3 4)
 >(filter '(#\a 276 "blubb" 5 blah 3 5 (4 995 54)) number?)
 (276 5 3 5)
<code id="4af43622f1dda">
(define filter 
  (lambda (liste funktion)
    (cond
      ((null? liste) '())
      ((funktion (car liste)) (cons (car liste) (filter (cdr liste) funktion)))
      (else
        (filter (cdr liste) funktion)))))
</code>
<run id="4af4362300acb">(filter '(1 2 3 4 5 6 7 8 9) even?)</run>
<check>
(listvergleich '(1 2 3 4) (filter '(-1 1 -2 2 0 -3 3 -4 4) groesser)) 
</check>

==Tabellieren==

Schreiben Sie eine Prozedur <tt>tabelliere</tt> zur Ausgabe einer Wertetabelle mit den Spalten <math>x</math> und <math>f(x)</math>, wobei <math>f</math> eine einstellige Funktion ist, die für <math>x=a,a+1,\ldots,b</math> protokolliert werden soll. <math>f</math>, <math>a</math> und <math>b</math> sollen beim Aufruf als Parameter übergeben werden.
     
'''Hinweis:''' Testen Sie auch mit Lambda-Ausdrücken für <math>f</math>.

'''Aufrufbeispiel:'''
 > (tabelliere (lambda (x) (* x x)) 0 5)
 (0 1 4 9 16 25)
<code id="4af43622f2627">
(define tabelliere
  (lambda (funktion untergrenze obergrenze)
    (display untergrenze) (display #\tab) (display (funktion untergrenze)) (newline)
    (if (>= untergrenze obergrenze)
      'schluss
      (tabelliere funktion (+ untergrenze 1) obergrenze))))
</code>
<run id="4af43623012b8">(tabelliere (lambda (x) (* x x)) 0 5)</run>
<check>listvergleich '(0 2 6 12 20 30) (tabelliere (lambda (x) (* (+ x 1) x)) 0 5)</check>

<language>Scheme</language>
==Compose==
Schreiben Sie eine Prozedur <tt>compose</tt>, die zwei einstellige Prozeduren <tt>proc1</tt> und <tt>proc2</tt> nimmt, diese verkettet und die Verkettungsprozedur "<tt>proc2</tt> nach <tt>proc1</tt>" zurückgibt. Wenden Sie <tt>compose</tt> auf geeignete Argumente an.
        
'''Aufrufbeispiel:'''
 > ((compose (lambda (n) (+ n n)) (lambda (n) (* n n))) 4)
 64
'''Wichtig:''' Die Klammersetzung im Aufrufbeispiel ist korrekt!     
                                     
<code id="4af43622f2d70">
(define compose 
  (lambda (proc1 proc2)
    (lambda (x) (proc2 (proc1 x)))))
</code>
<run id="4af4362301a70">((compose (lambda (n) (+ n n)) (lambda (n) (* n n))) 4)</run>
<check>(= ((compose (lambda (n) (* n n)) (lambda (n) (+ n 5))) 5) 30)</check>

==Primzahlen==
Verwenden Sie die oben definierte Prozedur <tt>filter</tt>, um aus der Liste der natürlichen Zahlen von 1 bis 1000 alle Primzahlen herauszusieben. Die verbleibenden Primzahlen sollen als Liste zurückgegeben werden.

<language>Scheme</language>
<language>Scheme</language>
===Natürliche Zahlen===                                                          
Sie benötigen eine Hilfsprozedur <tt>nliste</tt>, die eine Liste mit natürlichen Zahlen von 1 bis <tt>n</tt> erzeugt.

'''Aufrufbeispiel:'''
 > (nliste 5)
 (1 2 3 4 5)

<code id="4af43622f35a4">
(define nliste 
  (lambda (zahl)
    (if (= zahl 0)
       '()
       (append (nliste (- zahl 1)) (list zahl)))))
</code>
<run id="4af43623022e5">(nliste 1000)</run>

Außerdem benötigen Sie eine Prozedur <tt>prim?</tt>, die für eine gegebene natürliche Zahl <math>n</math> feststellt, ob sie eine Primzahl ist oder nicht. Verwenden Sie die folgende Prozedur <tt>alle-teiler</tt> zur Definition von <tt>prim?</tt>.

<code id="4af444a7e4af5">
(define alle-teiler
  (lambda (n t)
    (cond
      ((= t 1) '())
      ((zero? (remainder n t)) (cons t (alle-teiler n (- t 1))))
      (else
       (alle-teiler n (- t 1))))))
</code>
<run id="4af444a7e5e7b">(alle-teiler 24 24)</run>

Beachten Sie, dass die Prozedur <tt>alle-teiler</tt> die Zahl 1 nicht enthält. Mathematisch ist 1 Teiler jeder Zahl.

<code id="4af444a7e52c5">
(define prim?
  (lambda (n)
    (if (< n 2) 
        #f
        (equal? (list n)(alle-teiler n n)))))
</code>
<run id="4af444a7e6645">(prim? 11)</run>

Nun kann die Liste der Primzahlen berechnet werden:

'''Aufrufbeispiel:'''
 (filter (nliste 1000) prim?)
 >(2 3 5 7 11 13 17 19 ...)

<run id="4af4362302a67"> (filter (nliste 1000) prim?)</run>
<check>(equal? '(2 3 5 7 11 13 17 19) (filter (nliste 20) prim?))</check>

==Filter-Out==
Schreiben Sie analog zu <tt>filter</tt> eine Prozedur <tt>filter-out</tt>, die statt der Liste mit Primzahlen die Restliste ohne Primzahlen liefert. Die Primzahlen werden sozusagen herausgefiltert und aus der Ursprungsliste entfernt.

'''Aufrufbeispiel:'''
 > (filter-out (nliste 1000) prim?)
 (1 4 6 8 9 10 12 14 15 ...)
<code id="4af43623002f8">
(define filter-out
  (lambda (ls pred)
    (cond
      ((null? ls) '())
      ((pred (car ls)) (filter-out (cdr ls) pred))
      (else
        (cons (car ls) (filter-out (cdr ls) pred))))))
</code>
<run id="4af43623031d9"> (filter-out (nliste 1000) prim?)</run>
<check>(listvergleich '(1 4 6 8 9 10 12 14 15 16 18 20) (filter-out (nliste 20) prim?))</check>

[[Programmierparadigmen_-_Computerübungen|zur Übungsübersicht]]