Beispiellösung zum Übungsblatt aus Wiederholungstutorium 1

Werbung
Fachrichtung 6.2 — Informatik
Universität des Saarlandes
Tutorenteam der Vorlesung Programmierung 1
Programmierung 1 (Wintersemester 2015/16)
Wiederholungstutorium Lösungsblatt 1
(Rekursive Prozeduren)
Hinweis: Dieses Übungsblatt enthält von den Tutoren für das Wiederholungstutorium erstellte Aufgaben.
Die Aufgaben und die damit abgedeckten Themenbereiche sind für die Klausur weder relevant noch irrelevant.
Schnellkurs
Aufgabe 1.1 (Grundbegriffe)
Identifizieren Sie Bezeichner, Schlüsselwörter, Operatoren und Konstanten in folgendem Programm:
fun p x = x=0
val x = if ( p 3) then ∼1 else 3−2
Lösung 1.1:
Bezeichner:
Schlüsselwörter:
Operatoren:
Konstanten:
p, x
f un, =, val, if, (, ), then, else
=, , −
0, 3, 1, 2
Aufgabe 1.2 (Swap Swap)
Schreiben Sie eine Prozedur swap: int * int * int → int * int * int, die ein Tripel aus Zahlen erhält
und diese rotierend tauscht. Zum Beispiel soll swap(1,2,3) = (3,1,2) liefern. Schreiben Sie die Prozedur auf
drei Arten.
(a) Mit Projektion.
(b) Mit lokaler Deklaration (let-Ausdruck).
(c) Mit kartesischem Argumentmuster.
Lösung 1.2:
(a) fun swap ( t : int * int * int ) = (#3 t , #1 t , #2 t )
(b) fun swap t = let val (x ,y , z ) = t in (z ,x , y ) end
(c) fun swap (x ,y , z ) = (z ,x , y )
Aufgabe 1.3 (Minimum)
Schreiben Sie eine Prozedur min: int → int → int → int, die zu drei Zahlen die kleinste liefert, auf zwei
Arten:
(a) Benutzen Sie keine Hilfsprozedur und drei Konditionale.
(b) Benutzen Sie eine Hilfsprozedur und insgesamt ein Konditional.
Lösung 1.3:
(a) fun min x y z = if x<y then if x<z then x else z
else if y<z then y else z
1
(b) fun min ’ n m = if n<m then n else m
fun min x y z = min ’( x , min ’( y , z ))
Aufgabe 1.4 (Endrekursion)
Diskutieren Sie mit einem Partner über den Unterschied zwischen Rekursion und Endrekursion. Welchen Vorteil
hat Endrekursion? Betrachten Sie jetzt folgende Prozedur:
fun foo (a , b ) = if a=0 then b else foo ( a−1 , b+1)
(a) Ist foo endrekursiv?
(b) Geben Sie die Rekursionsfolge für den Aufruf foo(3,0) an.
(c) Geben Sie ein vollständiges Ausführungsprotokoll für den Aufruf foo(3,0) an. Das Auführungsprotokoll
umfasst 18 Ausführungsschritte.
Lösung 1.4:
Endrekursion stellt einen Spezialfall der Rekursion dar. Hierbei werden Rechenschritte ausschließlich in einem
Argument der endrekursiven Prozedur durchgeführt (Akkumulator). Dadurch wird Speicher gespart, da in diesem
Fall zuerst gerechnet wird, bevor die Prozedur mit dem aktualisierten Akkumulator aufgerufen wird. Zudem ist
in jedem Rekursionsschritt das aktuelle Zwischenergebnis verfügbar.
(a) Ja, die Prozedur ist endrekursiv, da in jedem Rekursionsschritt ausschließlich in einem Akkumulator
Rechenschritte ausgeführt werden.
(b) foo(3,0) → foo(2,1) → foo(1,2) → foo(0,3)
(c) foo (3 ,0) =
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
if 3=0 then 0 else foo (3−1 ,0+1)
if false then 0 else foo (3−1 ,0+1)
foo (3−1 ,0+1)
foo (2 ,0+1)
foo (2 ,1)
if 2=0 then 1 else foo (2−1 ,1+1)
if false then 1 else foo (2−1 ,1+1)
foo (2−1 ,1+1)
foo (1 ,1+1)
foo (1 ,2)
if 1=0 then 2 else foo (1−1 ,2+1)
if false then 2 else foo (1−1 ,2+1)
foo (1−1 ,2+1)
foo (0 ,2+1)
foo (0 ,3)
if 0=0 then 3 else foo (0−1 ,3+1)
if true then 3 else foo (0−1 ,3+1)
3
2
Rekursive Prozeduren schreiben
Aufgabe 1.5 (ganzzahlige Division)
Schreiben Sie zwei Prozeduren des Typs int → int → int, die das Ergebnis ganzzahliger Division m div n
(n 6= 0) durch wiederholte Subtraktion berechnen:
(a) Wobei m, n nicht negativ sind.
(b) Wobei m, n ganzzahlig sind.
Hinweis: Benutzen Sie bei (b) eine Hilfsprozedur, die das Vorzeichen des Ergebnisses festlegt. Verwenden Sie die
in (a) verwendete Prozedur, um das Ergebnis zu bestimmen.
Lösung 1.5:
(a) fun mydiv m n = if n<m then 0 else 1 + mydiv (m−n) n
(b) fun mydiv ’ m n = if m<0 then if n<0 then mydiv (∼m ) (∼n )
else ∼( mydiv (∼m ) n )
else if n>0 then mydiv m n
else ∼( mydiv m (∼n ))
Aufgabe 1.6 (Quersumme)
Schreiben Sie eine Prozedur quer: int → int, die die Quersumme einer nicht negativen Zahl berechnet.
Lösung 1.6:
fun quer x = if x div 10 = 0 then x
else x mod 10 + quer ( x div 10)
Aufgabe 1.7 (Stelligkeit)
Schreiben Sie eine Prozedur stell: int → int, die die Stelligkeit einer nicht negativen Zahl berechnet. Zum
Beispiel liefert stell(162) = 3.
Lösung 1.7:
fun stell x = if x div 10 = 0 then 1
else 1 + stell ( x div 10)
Aufgabe 1.8 (Von Ziffern und Zahlen)
Schreiben Sie eine Prozedur increase: int → int, die eine gegebene nicht negative Zahl in jeder Ziffer um
eins erhöht. Dabei soll die Ziffer 9 zu einer 0 erhöht werden und gleichzeitig die Ziffer, die links der 9 steht im
nächsten Schritt um zwei erhöht werden. Zum Beispiel liefert increase(190) = 301.
Lösung 1.8:
fun increase x = if x div 10 = 0 then x + 1
else 10 * increase ( x div 10) + ( x mod 10) + 1
Aufgabe 1.9
Schreiben Sie die jeweiligen Prozeduren mit normaler Rekursion und mit Endrekursion.
(a) Die Prozedur add: int * int → int soll die Summe zweier nicht negativer Zahlen durch Inkrementierung
berechnen.
3
(b) Die Prozedur mul: int * int → int soll das Produkt zweier nicht negativer Zahlen durch wiederholte
Addition berechnen.
(c) Die Prozedur pow: int * int → int soll die Potenz zweier nicht negativer Zahlen durch wiederholte
Multiplikation berechnen.
Hinweis: Sie dürfen für die endrekursive Lösung von mul und pow eine endrekursive Hilfsprozedur verwenden.
Lösung 1.9:
(a) rekursiv:
fun add (x , y ) = if y=0 then x else 1 + add (x , y−1)
endrekursiv:
fun add (x , y ) = if y=0 then x else add ( x+1 , y−1)
(b) rekursiv:
fun mul (x , y ) = if y=0 then 0 else x + mul (x , y−1)
endrekursiv:
fun mul ’ (a ,x , y ) = if y=0 then a else mul ’( a+x ,x , y−1)
fun mul (x , y ) = mul ’(0 , x , y )
(c) rekursiv:
fun pow (x , y ) = if y=0 then 1 else x * pow (x , y−1)
endrekursiv:
fun pow ’ (a ,x , y ) = if y=0 then a else pow ’( a *x ,x , y−1)
fun pow (x , y ) = pow ’(1 , x , y )
Aufgabe 1.10 (Reversion)
Schreiben Sie eine Prozedur rev: int → int, die eine nicht negative Zahl reversiert.
Hinweis: Verwenden Sie dazu eine endrekursive Hilfsprozedur.
Lösung 1.10:
fun rev ’ a x = if x div 10 = 0 then a *10 + x
else rev ’ ( a *10 + x mod 10) ( x div 10)
fun rev x = rev ’ 0 x
Aufgabe 1.11 (Natürliche Quadratwurzel)
Schreiben Sie eine Prozedur sqr: int → int, die die natürliche Quadratwurzel einer nicht negativen Zahl
berechnet.
Hinweis: Verwenden Sie eine endrekursive Hilfsprozedur.
Lösung 1.11:
fun w (k , n ) = if k * k > n then k else w ( k+1 , n )
fun sqrt n = w (1 , n ) − 1
Aufgabe 1.12 (Quadratzahlen)
Schreiben Sie eine Prozedur sqr: int → int, die durch wiederholte Addition das Quadrat einer nicht negativen
Zahl berechnet. Verwenden Sie dazu keine Hilfsprozedur.
4
1 + 3 + ... + 2n − 1 = n2
Hinweis: Es gilt für n > 0:
Lösung 1.12:
fun sqr x = if x=0 then 0
else 2* x−1 + sqr ( x−1)
Aufgabe 1.13 (Ziffernauftreten)
Schreiben Sie eine Prozedur count: int → int → int, die die Anzahl an Auftreten einer Ziffer in einer Zahl
berechnet. Zum Beispiel soll count 2 24212 = 3 liefern.
Lösung 1.13:
fun count x y = if y div 10 = 0 then if x=y then 1 else 0
else ( if y mod 10 = x then 1 else 0) + count x ( y div 10)
Programmiersprachliches
Aufgabe 1.14 (Baumdarstellung)
Geben Sie die Baumdarstellung der folgenden durch Zeichendarstellungen beschriebenen Phrasen und Typen an.
(a) int * int * int → bool * bool → int
(b) if x<3 then 3 else p 3
(c) val x = let fun f (x:int,y:int) : int = ∼(x+y) in f(1,2) + 3 + f(4,5) end
Lösung 1.14:
(a)
(b)
→
if
→
∗
∗
int
int
int
<
int
x
•
3
p
3
3
bool
bool
(a)
let
+
Programm
fun
f
x
∼
int
()
int
y
•
x
int
5
3
f
+
:
:
•
+
y
()
4
()
1
f
2
5
Aufgabe 1.15 (Prozeduren sind Werte)
Geben Sie die Tripeldarstellung der Prozedur an, zu der der folgende Ausdruck auswertet:
( fn ( x : int ) ⇒ fn ( b : bool ) ⇒ if b then x else 5) (2*3)
Lösung 1.15:
(fn b ⇒ if b then x else 5, bool → int, [x:=6])
Aufgabe 1.16 (Bezeichnerbindung)
Betrachten Sie das folgende Programm:
val x = ∼2+7
fun f ( y : int ) = x+y
fun g ( y : int ) : int = if y<x then 0 else y+g ( y−1)
(a) Geben Sie die Umgebung an, die die Ausführung des Programms in der Umgebung [] liefert.
(b) Geben Sie die Umgebung an, in der der Rumpf der Prozedur f bei der Ausführung des Aufrufs f 7
ausgeführt wird.
(c) Geben Sie die Umgebung an, in der der Rumpf der Prozedur g bei der Ausführung des Aufrufs g 13
ausgeführt wird.
Lösung 1.16:
(a) [ x := 5 ,
f := ( fun f y = x+y , int → int , [ x := 5])
g := ( fun g y = if y<x then 0 else y+g ( y−1) , int → int , [ x := 5])]
(b) [ x := 5 ,
f := ( fun f y = x+y , int → int , [ x := 5]) , y := 7]
(c) [ x := 5 ,
g := ( fun g y = if y<x then 0 else y+g ( y−1) , int → int , [ x := 5]) , y := 13]
Aufgabe 1.17
Welche Bindungen berechnet das folgende Programm?
fun
val
fun
val
f
x
g
x
( x : bool ) = if x then 1 else 0
= 5*7
( z : int ) = f ( z<x )<x
= g 5
Lösung 1.17:
f := ( fun f x = if x then 1 else 0 , bool → int , [])
g := ( fun g z = f ( z<x )<x , int → bool ,
[ f := ( fun f x = if x then 1 else 0 , bool → int , []) , x := 35])
x := true
6
Herunterladen