4/1 Technische Universität München WS 2012/13 Fakultät für Informatik Lösungsvorschläge zu Blatt 4 Dr. C. Herzog, M. Maalej 12. November 2012 Übungen zu Grundlagen der Programmierung Aufgabe 14 (Lösungsvorschlag) Terminierung rekursiver Funktionen Zur Lösung der vier Teilaufgaben suchen wir Eingabewerte, für die es möglich ist Abstiegsfunktionen, wie in der Vorlesung definiert, anzugeben. a) f_a(m,n) terminiert für alle n N: h : Z N N, h(m,n) = n. Es treten nur für n 0 rekursive Aufrufe auf, d.h. der Parameter n-1 des rekursiven Aufrufs ist nichtnegativ und es gilt: h(m + 1,n 1) = h(m + 2,n 1) = n 1 < n = h(n) f_a(m,n) terminiert nicht, falls n Z \ N: Für n Z\N ist n, n-1, n-2, n-3,... eine unendliche Folge, in der 0 nicht auftritt. Die durch den Aufruf f_a(m,n) angestoßene Folge rekursiver Aufrufe f_a(m+1,n-1), f_a(m+2,n-2), f_a(m+3,n-3),... erreicht also niemals den Terminierungsfall f_a(*,0). Dabei steht * für einen belieben Wert des ersten Parameters. b) f_b(m,n) terminiert für alle (m,n) Z Z mit m n: h : Z Z N, h(m,n) = n m. Es treten nur für n m 0, d.h. für n m > 0 im Fall m n, rekursive Aufrufe auf und es gilt: h(m,n 1) = n 1 m = n m 1 = h(m,n) 1 < h(m,n) h(m + 1,n) = n (m + 1) = n m 1 = h(m,n) 1 < h(m,n) f_b(m,n) terminiert nicht, falls m > n: Für m > n ist n,n 1,n 2,n 3,... eine unendliche Folge, in der m nicht auftritt. Die durch den Aufruf f_b(m,n) angestoßene Folge rekursiver Aufrufe f_b(m,n-1), f_b(m,n-2), f_b(m,n-3),... erreicht also niemals den Terminierungsfall m == n. c) f_c(m,n) terminiert für alle (m,n) Z Z mit m n und (n m) mod 2 = 0: h : Z Z N, h(m,n) = n m. Es treten nur für n m 0 rekursive Aufrufe auf und es gilt: h(m + 1,n 1) = n 1 (m + 1) = n 1 m 1 = h(m,n) 2 < h(m,n) (Achtung: Die Voraussetzung (n m) mod 2 = 0 stellt sicher, dass mit h(m,n) auch h(m + 1,n 1) in N liegt.)
4/2 f_c(m,n) terminiert nicht, falls m n und (n m) mod 2 = 1: Falls gilt (n m) mod 2 = 1 (d.h. falls die Differenz n m ungerade ist), dann bildet n m, (n 1) (m+1), (n 2) (m+2), (n 3) (m+3),... eine unendliche Folge ungerader Zahlen, in denen die 0 nicht auftritt. Die durch den Aufruf f_c(m,n) angestoßene Folge rekursiver Aufrufe f_c(m+1,n-1), f_c(m+2,n-2), f_c(m+3,n-3),... erreicht also niemals den Terminierungsfall m==n. f_c(m,n) terminiert nicht, falls m > n: Für m > n ist n m, (n 1) (m + 1), (n 2) (m + 2), (n 3) (m + 3),... eine unendliche Folge, in der die 0 nicht auftritt. Die durch den Aufruf f_c(m,n) angestoßene Folge rekursiver Aufrufe f_c(m+1,n-1), f_c(m+2,n-2), f_c(m+3,n-3),... erreicht also niemals den Terminierungsfall m==n. d) f_d(n) terminiert für alle n Z: h : Z N, h(m,n) = 100 n. Es treten nur für n 100 rekursive Aufrufe auf und es gilt: n < 100 h(200 n 1) = 100 (200 n 1) = (200 n 1) 100 = 99 n < 100 n = 100 n = h(n) n > 100 h(200 n + 1) = 100 (200 n + 1) = 100 (200 n + 1) = 101 + n < 100 + n = 100 n = h(n) Aufgabe 15 (Lösungsvorschlag) a) f(2,-1) f(0,2) f(-1,1) f(1,2) f(0,1) f(0,1) f(-1,0) f(2,2) f(1,1) f(1,1) f(0,0) f(1,1) f(0,0) f(0,0) f(-1,-1) b) Zum Nachweis der Terminierung verwenden wir die Abstiegsfunktion h : Z Z N, h(a,b) = b a. Es treten nur für b-a 0 rekursive Aufrufe auf und es gilt: Fall a < b: linker Aufruf: h(a + 1,b) = b (a + 1) = b (a + 1) = b a 1 < b a = b a rechter Aufruf: h(a,b 1) = (b 1) a = (b 1) a = b a 1 < b a = b a Fall a > b: linker Aufruf: h(b + 1,a) = a (b + 1) = a (b + 1) = a b 1 < a b = a b = b a rechter Aufruf: h(b,a 1) = (a 1) b = (a 1) b = a b 1 < a b = a b = b a Für jeden rekursiven Aufruf gilt also die Abstiegsbedingung. c) Beweis mittels vollständiger Induktion über n = b a
4/3 Induktionsanfang (n = 0): Sei b a = 0. Dann gilt a = b und in diesem Fall berechnet sich f(a,b) zu 1 = 2 0 = 2 b a. Induktionsvoraussetzung: Sei n + 1 = b a > 0 und für alle a, b mit n = b a die Behauptung f(a,b ) = 2 n bereits gezeigt. Induktionsschritt (n n + 1): 1. Fall : a < b. Dann gilt f(a,b) = f(a+1,b) + f(a,b-1). Wegen b (a + 1) = b (a + 1) = (b a) 1 = b a 1 = n und (b 1) a = (b a) 1 = b a 1 = n läßt sich die Induktionsvoraussetzung auf beide rekursive Aufrufe anwenden und f(a,b) berechnet sich zu 2 n + 2 n = 2 n+1 = 2 b a. 2. Fall : a > b. Dann gilt f(a,b) = f(b+1,a) + f(b,a-1). Wegen a (b + 1) = a (b + 1) = (a b) 1 = a b 1 = b a 1 = n und (a 1) b = (a b) 1 = a b 1 = b a 1 = n läßt sich auch hier die Induktionsvoraussetzung auf beide rekursive Aufrufe anwenden und f(a,b) berechnet sich wieder zu 2 n + 2 n = 2 n+1 = 2 b a. Aufgabe 16 (Lösungsvorschlag) public class Mathdienste { public int fac (int n) { return (n == 0)? 1 : n * fac (n-1); public double power (double x, int n) { return (n == 0)? 1 : power(x, n-1) * x; public double expn (double x, int n) { return (n == 0)? 1 : power(x,n)/fac(n) + expn(x,n-1); public class TestMath { public static void main (String[] args) { Mathdienste md = new Mathdienste (); System.out.println(md.expN(1,5)); Aufgabe 17 (Lösungsvorschlag) Markov-Algrithmen
4/4 a) (i) εaaaaa 5 0aaaaa 1 a1aaaa 2 aaa0aaa 1 aaaa1aa 2 aaaaaa0a 1 aaaaaaa1 4. aaaaaaa (ii) Das Ergebniswort besteht aus n + n/2 Zeichen a. Dabei steht der Operand / für die ganzzahlige Division natürlicher Zahlen. b) (i) 0a a1 (1) 0b b0 (2) 1a a2 (3) 1b b1 (4) 2a b0 (5) 2b b2 (6) 0. ε (7) 1. ε (8) 2. ε (9) ε 0 (10) (ii) Nein, da sich Eingabewort und Ergebniswort vom Alphabet her nicht unterscheiden und somit der Algorithmus immer wieder von vorne beginnen könnte. Aufgabe 18 Türme von Hanoi a) Für n = 0 ist die Lösung klar: Es ist nichts zu tun. Hat man bereits eine Zugfolge für n 1 Scheiben, dann ergibt sich daraus unmittelbar eine Zugfolge für n Scheiben: (A) Verlege n Scheiben von a nach b mittels Platz c wie folgt: Verlege n-1 Scheiben von a nach c mittels Platz b Setze eine Scheibe vom Platz a auf Platz b Verlege n-1 Scheiben von c nach b mittels Platz a Man beachte, dass beim Umlegen der n 1 oberen Scheiben die unterste nicht stört, weil sie größer als alle anderen ist. b) Es wird nur ein elementarer Schritt verwendet: Setze eine Scheibe vom Platz a auf Platz b. c) Die Anzahl Anz(n) der benötigten elementaren Schritte, um einen Turm aus n Scheiben zu versetzen, ist: Anz(1) = 1 Anz(2) = 1+2*Anz(1) = 1+2 Anz(3) = 1+2*Anz(2) = 1+2*(1+2) Anz(4) = 1+2*Anz(3) = 1+2*(1+2*(1+2)) = 1+ 2+ 4+8 Anz(n) = 2 n 1 d) Das Verfahren ist deterministisch, weil die Schrittfolge eindeutig festgelegt ist. Es ist determiniert, weil das Ergebnis eindeutig ist, es ist terminierend, weil es nach endliche vielen Schritten endet. Eine andere Lösung: Wir denken uns die drei Plätze im Kreis angeordnet, und zwar, wenn n ungerade ist, so: auf a folgt b, darauf c, dann wieder a
4/5 und wenn n gerade ist, so auf a folgt c, darauf b, dann wieder a. Das folgende Verfahren gibt für 0 < n die Schrittfolge als Wiederholung von zwei elementaren Schritten an. (B) Verlege n Scheiben von a nach b mittels Platz c wie folgt: Lege die kleinste Scheibe einen Platz weiter Wiederhole (2^{n-1-1)-mal: Bewege eine Scheibe, aber nicht die kleinste Lege die kleinste Scheibe einen Platz weiter Im folgenden Beispiel sind Scheiben durch Zahlen dargestellt, die ihre Durchmesser wiedergeben. Fett gedruckt ist jeweils die Scheibe, die zuletzt bewegt wurde. Man beachte, wie die Turmspitze wandert, und zwar zunächst die 1 nach b, dann 12 nach c, dann 123 nach b - unabhängig jeweils vom darunterliegenden Rest des Turms: a b c 12345.......2345...1.....345...1...2..345......12...45...3...12..145...3...2..145...23......45..123...... Dieses Verfahren führt zur selben Schrittfolge und zum selben Ergebnis wie Verfahren (A). Es ist somit auch deterministisch, determiniert und terminierend.anmerkung: Der Turm der buddistischen Mönche, der auf diese Weise täglich um einen Stein versetzt wird und die Tage bis zum Weltuntergang zählt, hat eine Höhe von 64 Scheiben. Das Umsetzen wird also mehr als 10 15 Jahre dauern. Übrigens ist (2 64 1) auch die Zahl der Reiskörner, die jenem König dadurch als Belohnung abverlangt wurde, dass er beginnend bei 1 auf jedes folgende Feld des Schachbretts die doppelte Anzahl Körner legen sollte.