Übungen zur Rekursion\374

Werbung
ÜBUNGEN ZUR REKURSION
Aufgabe 1: Auf einem früheren Arbeitsblatt wurde eine rekursive DELPHI-Funktion zur
Berechnung der Quadratzahl zu einer natürlichen Zahl n vorgestellt, welche
mathematisch wie folgt definiert war:
quad (n − 1) + n + n − 1 n > 1
quad (n) =
1
n =1
a) Stellen Sie den rekursiven Abstieg grafisch dar.
b) Ermitteln Sie für den Funktionsaufruf quad(5) die Gesamtanzahl an Vergleichs- und
Strichoperationen.
c)
Schreiben Sie eine DELPHI-Function quad2(n: integer): integer, welche die
Quadratzahl nun iterativ berechnet. Nutzen Sie dazu folgende Beziehung:
1² = 1, 2² = 3 + 1, 3² = 5 + 3 + 1, 4² = 7 + 5 + 3 + 1, 5² = 9 + 7 + 5 + 3 + 1, ...
d) Ermitteln Sie auch zu Ihrer Funktion die Gesamtanzahl an Vergleichs und
Strichoperationen. Vergleichen Sie mit Teilaufgabe b.
Hinweis: Die FOR-Schleife for i:= 1 to n beinhaltet implizit die Addition
i:= i + 1 sowie den Vergleich i <= n.
Aufgabe 2: Schreiben Sie jeweils eine rekursive Prozedur, welche die folgenden Grafiken
erzeugt:
a)
b)
c)
Aufgabe 3: Hinter den Ziffernfolgen 1, 121, 1213121, 121312141213121,
1213121412131215121312141213121, ... verbirgt sich ein interessantes
rekursives Bildungsgesetz.
a) Beschreiben sie dieses Bildungsgesetz in eigenen Worten.
b) Schreiben Sie eine Function Ziffernfolge (n: Integer): String, welche die
n-te Ziffernfolge als String zurückgibt.
c)
Warum sollte die Funktion einen String und keine Zahl zurückgeben? Begründen Sie!
Aufgabe 4: Betrachten Sie die folgende DELPHI-Prozedur:
procedure TF_Wort.Wort(n: Integer; w: string);
var i: char;
begin
if n=0
then M_Ausgabe.Lines.Add(w)
else begin
for i:= 'A' to 'F'
do Wort(n-1,w+i)
end;
end;
a) Beschreiben Sie in eigenen Worten die Wirkung der Prozedur. Welche Ausgabe wird
getätigt, wenn die Prozedur mit Wort(3,’’) gestartet wird?
b) Wie muss man das Programm abändern, damit die produzierten Worte nur aus
unterschiedliche Buchstaben bestehen.
Hinweis: Implementierung auch ohne Hilfe des Mengentyps (Set of ...) möglich. Dazu
müssen nur in dem vordefinierten Wort ´ABCDEF´ lediglich Buchstaben
getauscht anstatt angehängt werden.
Aufgabe 5: Wie viele Möglichkeiten gibt es, ein DM-Stück in Ein-, Zwei-, Fünf-, Zehn- und
Fünfzigpfennigstücke zu wechseln? Allgemein: Ein Land hat k Münzwerte
m[1] = 1, m[2] = ?, ..., m[k] = ?. Auf wie viele Arten kann man b Geldeinheiten
mit Hilfe dieser Münzen bezahlen?
a) Machen Sie sich klar, dass es für 10 Pfennig insgesamt 11 verschiedene Möglichkeiten
der Bezahlung gibt.
b) Entwickeln Sie eine rekursive Function a(b, k: Integer): Integer, welche die
Anzahl der Möglichkeiten, b Geldeinheiten mit k verschiedenen Münzen m[1..k] zu
zahlen, berechnet.
Hinweis: Sei a(b,k) die Anzahl der Möglichkeiten, b Geldeinheiten mit Münzen zu
bezahlen, deren Werte in der Reihung m[1..k]
gespeichert sind; m[1] = 1. Dann lässt sich das
Problem auf das kleinere Problem, den Betrag
b – m[k] zu wechseln, reduzieren. Es gibt aber
a(b−m[k],k) Möglichkeiten, unter
Verwendung von m[k] zu zahlen, und a(b,k−1)
Möglichkeiten, ohne die Münze vom Wert
m[k] zu zahlen.
c)
Sei m[1..5] = (1,2,5,10,50). Stellen Sie den rekursiven
Abstieg für den Aufruf a(10,5) grafisch dar
(Baumdiagramm). Begründen Sie damit die 11
Bezahlungsmöglichkeiten aus Teilaufgabe a.
d) Entwickeln Sie eine Prozedur, welche alle Möglichkeiten
der Bezahlung explizit in einem Memofenster auflistet
(siehe rechts abgedrucktes Beispiel-Formular).
LÖSUNGEN ZU DEN ÜBUNGEN
Aufgabe 1: a) + b)
Quad(5)
|
Quad(5−1)
+5+5−1
|
Quad(4−1)
+4+4−1
|
Quad(3−1)
+3+3−1
|
Quad(2−1) + 2 + 2 − 1
|
1
c)
Strichop.: Verleiche:
1
4
1
4
1
4
1
4
1
16
5
Function quad2(n: integer): integer;
Var i, Ergebnis: Integer;
Begin
Ergebnis:= 0
for i:= 1 to n
do begin
Ergebnis:= Ergebnis + i + i – 1;
end;
End;
d) Anzahl Strichop.: 20 (da i:= i + 1); Anzahl Vergleiche: 6 (da bei i = 6 auch geprüft wird).
Aufgabe 2: a) Procedure Baum(n: Integer; Laenge: Real);
Begin
VW(Laenge);
if n>1
then begin
DL(45);
Baum(n-1, Laenge*0.7)
DR(90);
Baum(n-1, Laenge*0.7)
DL(45);
end;
RW(Laenge);
End;
b) Procedure Quadrat(n: Integer; Laenge: Real);
Begin
VW(Laenge/2);
for i := 1 to 3
do begin
DR(135);
if n>1 then Quadrat(n-1, Laenge/2);
DR(135);
VW(Laenge);
end;
DR(135);
if n>1 then Quadrat(n-1, Laenge/2);
DR(135);
VW(Laenge/2);
End;
c)
Procedure Trauerweide(n: Integer; Laenge: Real);
Begin
VW(Laenge); DL(15);
if n>1 then
VW(Laenge);
if n>1 then
VW(Laenge);
if n>1 then
VW(Laenge);
RW(Laenge);
if n>1 then
VW(Laenge);
if n>1 then
VW(Laenge);
if n>1 then
VW(Laenge);
RW(Laenge);
End;
Trauerweide
DR(15);
Trauerweide
DR(15);
Trauerweide
RW(Laenge);
DR(45);
(n-1, Laenge);
(n-1, Laenge);
(n-1, Laenge);
DL(15); RW(Laenge); DL(15);
Trauerweide (n-1, Laenge);
DL(15);
Trauerweide (n-1, Laenge);
DL(15);
Trauerweide (n-1, Laenge);
RW(Laenge); DR(15); RW(Laenge); DR(15);
DL(30); RW(Laenge);
Aufgabe 3: a) Eine neue Zahl entsteht durch Verdopplung der vorangegangenen Zahl,
wobei die Verdopplung durch die Ziffer der Rekursionstiefe getrennt wird.
b) function zf(n: integer): string;
begin
if n<1 then zf:= ''
else zf:= zf(n-1)+IntToStr(n)+zf(n-1);
end;
c) Integer-Zahlen sind auf den Zahlenbereich −215 .. +215−1 begrenzt. Selbst Longint-Zahlen
(−231 .. +231−1) reichen als Zahlenbereich nicht aus. Also kann man die Ziffernfolge besser
als Zeichenkette auffassen.
Aufgabe 4: a) Es werden alle Wörter mit drei Buchstaben über dem Alphabet A..F gebildet.
AAA, AAB, AAC, ... , AAF, ABA, ABB, ..., AFF, BAA, BAB, ..., FFF
(insgesamt 63 Wörter).
b) Procedure TF_Wortbildung.Permut(wort: string; n: integer);
var i: integer;
begin
if n = length(wort)
then Memo1.Lines.Add(wort)
else for i:= n to length(wort)
do begin
Vertausche(wort[i], wort[k]);
Permut(wort, n+1);
end;
end;
{ Sollte klar sein }
Eine Lösung mit Verwendung des Mengentyps wäre wie folgt:
type TZeichen = 'A'..'F';
TMZeichen = Set of TZeichen;
...
procedure TF_Wortbildung.Permut(wort: string; n: Integer; MZeichen: TMZeichen);
var i: TZeichen;
begin
if n=0
then M_Ausgabe.Lines.Add(wort)
else for i:= 'A' to 'F'
do if i in MZeichen then Permut(wort+i, n-1, MZeichen-[i])
end;
Aufgabe 5: a) 10; 5+5; 5+2+2+1; 5+2+1+1+1; 5+1+1+1+1+1; 2+2+2+2+2; 2+2+2+2+1+1;
2+2+2+1+1+1+1; 2+2+1+1+1+1+1+1; 2+1+1+1+1+1+1+1+1;
1+1+1+1+1+1+1+1+1+1
b) const muenzen:array[1..5] of integer=(1,2,5,10,50);
...
function Anzahl(b: integer; k: integer): integer;
begin
if k=1
then Anzahl:= 1
else if b<muenzen[k]
then Anzahl:= Anzahl(b,k-1)
else Anzahl:= Anzahl(b-muenzen[k],k) + Anzahl(b,k-1);
end;
c) Die Rekursionsanker sind jeweils unterstrichen. An diesen Stellen wird die Anzahl um 1
erhöht. Insgesamt 11 Rekursionsanker Anzahl = 11.
Anzahl(10,5)
A(10,4)
A(0,4)
+
A(0,3)
A(10,3)
A(5,3)
+
A(0,2)
A(0,3)
+
A(5,2)
A(0,1)
A(0,2)
A(3,2) +
A(0,1)
A(10,2)
A(8,2)
+
A(10,1)
A(6,2)
+
A(8,1)
A(1,2) + A(3,1)
A(4,2)
+
A(6,1)
A(1,1)
A(2,2)
+
A(4,1)
A(0,2)
+
A(2,1)
A(5,1)
A(0,1)
d) procedure TF_Wechseln.Wechseln(b: Integer; k: integer; w: string);
var i: integer;
begin
if b=0
then M_Ausgabe.Lines.Add(w)
else begin
if w<>'' then w:= w+'+';
for i:= k downto 1
do if b>=muenzen[i]
then Wechseln(b-muenzen[i],i,w+IntToStr(muenzen[i]))
end;
end;
Herunterladen