Grundlagen der funktionsorientierten Programmierung mit SCHEME/Bedingte Ausdrücke
Aus ProgrammingWiki
Wiki-Quelltext dieser Seite.
<language>SchemeJS</language>
<code id="5ba0d4cd27a8d" hidden>
(define zufallszahl
(lambda (a b)
(+ a (random (- b a -1)))))
(define char-downcase
(lambda (z)
(let ([nr (char->integer z)])
(if (and (> nr 64) (< nr 91))
(integer->char (+ nr 32))
z))))
(define char-upcase
(lambda (z)
(let ([nr (char->integer z)])
(if (and (> nr 96) (< nr 123))
(integer->char (- nr 32))
z))))
(define substring?
(lambda (zk1 zk2)
(cond
[(> (string-length zk1) (string-length zk2)) #f]
[(equal? zk1 (substring zk2 0 (string-length zk1))) #t]
[else
(substring? zk1 (substring zk2 1 (string-length zk2)))])))
(define klassenstaerke?
(lambda (proz a b)
(let* ([z (zufallszahl a b)] [test (apply proz (list z))])
(cond
[(void? test) #f]
[(not (string? test)) #f]
[(and (or (< z 10) (> z 32)) (substring? "unzul" (string-downcase test))) #t]
[(and (< z 16) (substring? "gering" (string-downcase test))) #t]
[(and (< z 21) (substring? "ideal" (string-downcase test))) #t]
[(and (< z 26) (substring? "normal" (string-downcase test))) #t]
[(and (< z 33) (substring? "ho" (string-downcase test))) #t]
[else #f]))))
</code>
== Bedingte Ausdrücke in Scheme ==
Bedingte Ausdrücke sind Programmstrukturen, mit denen der ''Wert'' eines Ausdrucks von bestimmten ''Bedingungen'' abhängig gemacht werden kann.
<table border="1" cellspacing="1" cellpadding="4">
<tr>
<th width="37%">Grundform</th>
<th width="30%">Alternative</th>
<th width="33%">Fallauswahl</th>
</tr>
<tr>
<td>
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td height="160" width="500" valign="top">
<code id="4c9cb9191269f">
(define gewichtspruefer
(lambda (masse)
(cond
[(< masse 60) 'leichtgewicht]
[(< masse 80) 'normalgewicht]
[(< masse 100) 'schwergewicht]
[else
'uebergewicht])))
</code>
</td>
</tr>
<tr>
<td height="100" width="500" valign="top">
<run id="4c7ebb1941f9b">(gewichtspruefer 75)</run>
</td>
</tr>
</table>
</td>
<td>
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td height="160" width="500" valign="top">
<code id="4c7ebb1941871">
(define my-abs
(lambda (x)
(if (< x 0)
(- x)
x)))
</code>
</td>
</tr>
<tr>
<td height="100" width="500" valign="top">
<run id="4c7ebb19420c5">(my-abs -3.45)</run>
</td>
</tr>
</table>
</td>
<td>
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td height="160" width="500" valign="top">
<code id="4c9e20fdaaf21">
(define vokal?
(lambda (zeichen)
(case zeichen
[(#\a #\e #\i #\o #\u) #t]
[(#\A #\E #\I #\O #\U) #t]
[else #f])))
</code>
</td>
</tr>
<tr>
<td height="100" width="500" valign="top">
<run id="4c9e20fdab08f">(vokal? #\o)</run>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td valign="top">
'''Beachte:'''<br />
<ul>
<li>die angegebenen Bedingungen werden in der vorgegebenen Reihenfolge evaluiert,</li>
<li>sobald sich zum ersten Mal der Wahrheitswert <tt>#t</tt> ergibt, werden keine weiteren Bedingungen untersucht
(selbst dann nicht, wenn ein fehlerhafter Ausdruck wie <tt>(/ 4 0)</tt> erscheint) – die Evaluation wird an dieser Stelle beendet,</li>
<li>else wird immer zu <tt>#t</tt> evaluiert, sodass bei seiner Evaluation immer der nachfolgende Ausdruck abgearbeitet wird.</li>
</ul>
</td>
<td valign="top">
'''Beachte:'''<br />
<ul>
<li>der <tt>else</tt>–Teil ist i.A. obligatorisch,</li>
<li>wenn er entfallen kann, sollten unbestimmte Rückgabewerte, wie sie bei
<pre>
(define my-sqrt
(lambda (x)
(if (>= x 0) (sqrt x))))
</pre>
auftreten können, vermieden werden,</li>
<li>in den beiden Teilen <tt>if</tt> und <tt>else</tt> darf nur ein Ausdruck stehen, anderenfalls muss mit
<tt>(begin <Ausdruck> ... <Ausdruck>)</tt> ein ''zusammengesetzter Ausdruck'' gebildet werden.</li>
</ul>
</td>
<td valign="top">
'''Beachte:'''<br />
<ul>
<li>zunächst wird der nach <tt>case</tt> folgende Ausdruck evaluiert,</li>
<li>in einer Suche von oben nach unten wird festgestellt, in welcher Auswahlmenge sein Wert vorkommt,</li>
<li>der zu dieser Menge gehörende Ausdruck wird evaluiert und als Wert des gesamten <tt>case</tt>–Ausdrucks zurückgegeben,</li>
<li>falls der Wert in keiner Menge enthalten ist, bildet der Wert nach <tt>else</tt> das Resultat.</li>
</ul>
</td>
</tr>
</table>
== Aufgaben ==
<ol>
<li>
=== Signumfunktion ===
Schreiben Sie eine Prozedur für die einstellige Funktion <tt>signum</tt>, die als Funktionswerte
-1, 1 oder 0 entsprechend des Vorzeichens der als Argument übergebenen Zahl zurückgibt.<br />
'''Beispiele:'''
<pre>
> (signum -337.8436) --> -1
> (signum 0) --> 0
> (signum (/ 34 45)) --> 1
</pre>
<code id="4c7ebb1941ac3">
(define signum
(lambda (x)
...))
</code>
<check>
(and (= (signum -337.8436) -1) (= (signum 0) 0) (= (signum (/ 34 45)) 1))
</check>
<run id="4c7ebb1942316">
(signum -337.8436)
</run>
</li>
<li>
=== Palindromprüfer ===
Entwickeln Sie das Prädikat <tt>palindrom?</tt>, das zu einer übergebenen Zeichenkette entscheidet, ob sie vor- und rückwärts gelesen gleich lautet.<br />
'''Beispiele:'''
<pre>
> (palindrom? "informatik") --> #f
> (palindrom? "otto") --> #t
</pre>
'''Hinweis:''' Sie können zur Lösung folgende Sprachelemente nutzen:
<pre>
> (equal? "otto" "otto") --> #t
> (reverse '(a b c d e)) --> (e d c b a)
</pre>
<code id="525485b6ecde6">
(define palindrom?
(lambda (zk)
...))
</code>
<check>
(and (palindrom? "einnegermitgazellezagtimregennie") (palindrom? "rentner") (not (palindrom? "informatik")))
</check>
<run id="525485b6eceec">
(palindrom? "otto")
</run>
</li>
<li>
=== Klassenstärkenprüfer ===
Lehrer und Schüler bewerten Klassenstärken etwa mit folgenden Einschätzungen:
* 10 ... 15: geringe Klassenstärke,
* 16 ... 20: ideale Klassenstärke,
* 21 ... 25: normale Klassenstärke,
* 26 ... 32: hohe Klassenstärke,
Alle anderen Schülerzahlen sind unzulässig.
Implementieren Sie einen "Klassenstärkenprüfer" als bedingten Ausdruck mit den Sprachelementen:
* <tt>cond</tt>
* <tt>if</tt>
* <tt>case</tt>.
Die Prozeduren sollen das Bewertungsergebnis als Zeichenkette zurückgeben.
<code id="4c7ebb1941bef">
(define klassenstaerke1
(lambda (anzahl)
(cond
...)))
</code>
<check>
(and (klassenstaerke? klassenstaerke1 1 9)
(klassenstaerke? klassenstaerke1 10 15)
(klassenstaerke? klassenstaerke1 16 20)
(klassenstaerke? klassenstaerke1 21 25)
(klassenstaerke? klassenstaerke1 26 32)
(klassenstaerke? klassenstaerke1 33 100))
</check>
<run id="4c7ebb194248a">
(klassenstaerke1 12)
</run>
<code id="4c7ebb1941d1d">
(define klassenstaerke2
(lambda (anzahl)
(if
...)))
</code>
<check>
(and (klassenstaerke? klassenstaerke2 1 9)
(klassenstaerke? klassenstaerke2 10 15)
(klassenstaerke? klassenstaerke2 16 20)
(klassenstaerke? klassenstaerke2 21 25)
(klassenstaerke? klassenstaerke2 26 32)
(klassenstaerke? klassenstaerke2 33 100))
</check>
<run id="4c7ebb19425b3">
(klassenstaerke2 21)
</run>
<code id="4c7ebb1941e4e">
(define klassenstaerke3
(lambda (anzahl)
(case
...)))
</code>
<check>
(and (klassenstaerke? klassenstaerke3 1 9)
(klassenstaerke? klassenstaerke3 10 15)
(klassenstaerke? klassenstaerke3 16 20)
(klassenstaerke? klassenstaerke3 21 25)
(klassenstaerke? klassenstaerke3 26 32)
(klassenstaerke? klassenstaerke3 33 100))
</check>
<run id="4c7ebb19426de">
(klassenstaerke3 38)
</run>
</li>
<li>
=== Konstruierbarkeit von Dreiecken ===
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td valign="top">
Zu drei beliebig gegebenen Seitenlängen kann nicht in jedem Fall ein Dreieck konstruiert werden (vgl. Abbildung).<br />
Vervollständigen Sie das Prädikat <tt>konstruierbar?</tt>, mit dem geprüft werden soll, ob ein Dreieck zu den gegebenen Seitenlängen <tt>a</tt>, <tt>b</tt> und <tt>c</tt> konstruierbar ist.<br />
Beachten Sie dabei, dass diese Seitenlängen in einer beliebigen Reihenfolge gegeben sein können.
'''Beispiele:'''
<pre>
> (konstruierbar? 3 4 5) --> #t
> (konstruierbar? 2 7 2) --> #f
</pre>
</td>
<td valign="top">
[[Bild:Dreieckskonstruktion1.gif|miniatur|hochkant=2|Zur Konstruierbarkeit von Dreiecken]]
</td>
</tr>
</table>
'''Hinweis:''' Sie können zur Lösung die variabelstellige Prozedur <tt>max</tt> nutzen:
<pre>
> (max 3 4 5 6 7 5 7 2) --> 7
</pre>
<code id="507197059a4a1">
(define konstruierbar?
(lambda (a b c)
...))
</code>
<check>
(and (konstruierbar? 3 4 5) (not (konstruierbar? 2 7 2)) (not (konstruierbar? 9 3 6)) (konstruierbar? 2 6 7))
</check>
<run id="507197059a587">
(konstruierbar? 3 4 5)
</run>
</li>
</ol>