Lösungen - Lehr- und Forschungsgebiet Informatik 2
Lösungen - Lehr- und Forschungsgebiet Informatik 2
Lösungen - Lehr- und Forschungsgebiet Informatik 2
- Keine Tags gefunden...
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
RHEINISCH-<br />
WESTFÄLISCHE<br />
TECHNISCHE<br />
HOCHSCHULE<br />
AACHEN<br />
LEHR- UND FORSCHUNGSGEBIET<br />
INFORMATIK 2<br />
RWTH Aachen · D-52056 Aachen · GERMANY<br />
http://programmierung.informatik.rwth-aachen.de<br />
LuFG<br />
<strong>Informatik</strong> II<br />
Prof. Dr. Jürgen Giesl<br />
Carsten Fuhs, Peter Schneider-Kamp, Stephan Swiderski<br />
Übung Programmierung WS 2007/08 - Blatt 3<br />
(Lösungsvorschlag)<br />
Aufgabe 1<br />
a) Ja. Eine Schleife der Form<br />
while (B) {<br />
P<br />
}<br />
lässt sich gleichwertig in die Form<br />
if (B) {<br />
do {<br />
P<br />
} while (B);<br />
}<br />
überführen.<br />
b) Ja. Eine Schleife der Form<br />
do {<br />
P<br />
} while (B);<br />
lässt sich gleichwertig in die Form
{<br />
}<br />
P;<br />
for ( ; B; ) {<br />
P<br />
}<br />
überführen.
Aufgabe 2<br />
Listing 1: Fibfor.java<br />
1 /∗ Das Programm berechnet zur Eingabe n die n−te Fibonacci −Zahl .<br />
2 ∗ Dabei werden ausser for −Schleifen keine anderen Schleifentypen<br />
3 ∗ verwendet .<br />
4 ∗<br />
5 ∗ Autor : Antje Nowack , Carsten Fuhs<br />
6 ∗ Erst ellt : 05.11.2001<br />
7 ∗ Letzte Aenderung : 05.11.2007<br />
8 ∗/<br />
9<br />
10 public class Fibfor {<br />
11<br />
12 public static void main (String [ ] arguments ) {<br />
13<br />
14 // Eingabe<br />
15 System .out .println (” Bitte geben Sie eine natuerliche Zahl ein : ” ) ;<br />
16 int n = IO .readInt ( ) ;<br />
17<br />
18 // a0 <strong>und</strong> a1 enthalten jeweils aufeinanderfolgende Fibonacci −Zahlen .<br />
19 int a0 = 0;<br />
20 int a1 = 1;<br />
21<br />
22 // res wird zum Zwischenspeichern benutzt <strong>und</strong> enthaelt am Ende<br />
23 // das Ergebnis<br />
24 int res = 0;<br />
25<br />
26 if (n == 1) {<br />
27 res = 1;<br />
28 }<br />
29<br />
30 // n − 1 Schleifendurchlaeufe<br />
31 for ( int j = 1; j < n ; ++j) {<br />
32<br />
33 // a0 enthaelt jeweils die zu j − 1 gehoerige Fibonacci −Zahl ,<br />
34 // a1 enthaelt die zu j gehoerige Fibonacci −Zahl , <strong>und</strong><br />
35 // res enthaelt die zu j + 1 gehoerige Fibonacci −Zahl .<br />
36 res = a0 + a1 ;<br />
37<br />
38 a0 = a1 ;<br />
39 a1 = res ;<br />
40 }<br />
41<br />
42 // Ausgabe<br />
43 System .out .println (”Die ” + n + ”−te Fibonacci−Zahl i s t ” + res ) ;<br />
44 }<br />
45 }
Listing 2: Fibwhile.java<br />
1 /∗ Das Programm berechnet zur Eingabe n die n−te Fibonacci −Zahl .<br />
2 ∗ Dabei werden ausser while −Schleifen keine anderen Schleifentypen<br />
3 ∗ verwendet .<br />
4 ∗<br />
5 ∗ Autor : Antje Nowack , Carsten Fuhs<br />
6 ∗ Erst ellt : 05.11.2001<br />
7 ∗ Letzte Aenderung : 05.11.2007<br />
8 ∗/<br />
9<br />
10 public class Fibwhile {<br />
11<br />
12 public static void main (String [ ] arguments ) {<br />
13<br />
14 // Eingabe<br />
15 System .out .println (” Bitte geben Sie eine natuerliche Zahl ein : ” ) ;<br />
16 int n = IO .readInt ( ) ;<br />
17<br />
18 // a0 <strong>und</strong> a1 enthalten jeweils aufeinanderfolgende Fibonacci −Zahlen .<br />
19 int a0 = 0;<br />
20 int a1 = 1;<br />
21<br />
22 // res wird zum Zwischenspeichern benutzt <strong>und</strong> enthaelt am Ende<br />
23 // das Ergebnis<br />
24 int res = 0;<br />
25<br />
26 if (n == 1) {<br />
27 res = 1;<br />
28 }<br />
29<br />
30 // Laufvariable<br />
31 int j = 1;<br />
32<br />
33 // n − 1 Schleifendurchlaeufe<br />
34 while (j < n) {<br />
35<br />
36 // a0 enthaelt jeweils die zu j − 1 gehoerige Fibonacci −Zahl ,<br />
37 // a1 enthaelt die zu j gehoerige Fibonacci −Zahl , <strong>und</strong><br />
38 // res enthaelt die zu j + 1 gehoerige Fibonacci −Zahl .<br />
39 res = a0 + a1 ;<br />
40<br />
41 a0 = a1 ;<br />
42 a1 = res ;<br />
43<br />
44 // Laufvariable um 1 erhoehen .<br />
45 ++j ;<br />
46 }<br />
47<br />
48 // Ausgabe<br />
49 System .out .println (”Die ” + n + ”−te Fibonacci−Zahl i s t ” + res ) ;
50 }<br />
51 }
Aufgabe 3<br />
Listing 3: Mastermind.java<br />
1 /∗ Das Programm simuliert das Spiel Mastermind.<br />
2 ∗ Hierbei erzeugt der Computer z u f aellig ein Geheimwort aus<br />
3 ∗ vier Zeichen , welches der Benutzer raten muss .<br />
4 ∗<br />
5 ∗ Autor : Antje Nowack , Carsten Fuhs , Stephan Swiderski<br />
6 ∗ Erst ellt : 05.11.2001<br />
7 ∗ Letzte Aenderung : 06.11.2007<br />
8 ∗/<br />
9<br />
10 public class Mastermind {<br />
11<br />
12 public static void main (String [ ] args ) {<br />
13 // Laufvariable fuer die do−while −Schleife<br />
14 int j = 1;<br />
15<br />
16 // g1 , g2 , g3 , g4 enthalten spaeter die Zeichen des Geheimwortes<br />
17 char g1 , g2 , g3 , g4 ;<br />
18<br />
19 /∗ eingabe i s t jeweils das geratene Wort ,<br />
20 ∗ <strong>und</strong> e1 , e2 , e3 , e4 sind seine Zeichen<br />
21 ∗/<br />
22 String eingabe ;<br />
23 char e1 , e2 , e3 , e4 ;<br />
24<br />
25 // erstes Zeichen des Geheimwortes aus dem Wertebereich { ’A’ , . . . , ’H’}<br />
26 g1 = Zufall .zufallszeichen ( ’H’ ) ;<br />
27<br />
28 /∗ Nun wird das zweite Zeichen des Geheimwortes bestimmt . Da g1 <strong>und</strong> g2<br />
29 ∗ nicht gleich sein duerfen , stehen fuer die Wahl von g2 nur noch<br />
30 ∗ 7 Zeichen zur Verfuegung . Um dies umzusetzen , wird wie f olgt<br />
31 ∗ vorgegangen :<br />
32 ∗ 1. Waehle ein Zeichen aus dem Wertebereich { ’A’ , . . . , ’G’}<br />
33 ∗ 2. Wenn das gewaehlte Zeichen < g1 ist , so i s t dies das zweite<br />
34 ∗ geratene Zeichen .<br />
35 ∗ 3. Sonst wird 1 hinzuaddiert , um das zweite Zeichen zu erhalten<br />
36 ∗ ( Beachte : Z.B. ’A’ + 1 == ’B ’).<br />
37 ∗<br />
38 ∗ Somit wird das zweite Zeichen aus dem Bereich<br />
39 ∗ { ’A’ , . . . , g1 −1, g1+1, . . . , ’H’} gewaehlt .<br />
40 ∗/<br />
41<br />
42 g2 = Zufall .zufallszeichen ( ’G’ ) ;<br />
43 if (g2 >= g1) {<br />
44 ++g2 ;<br />
45 }<br />
46<br />
47 /∗ Das Vorgehen fuer das dri tte Zeichen is t aehnlich dem Vorgehen
48 ∗ fuer das zweite Zeichen . Hier wird zunaechst ein Zeichen aus dem<br />
49 ∗ Wertebereich { ’A’ , . . . , ’F’} gewaehlt . Die moeglichen Zeichen sind<br />
50 ∗ diejenigen aus der Menge<br />
51 ∗ { ’A’ , . . . , g1 −1, g1+1, . . . , g2 −1, g2+1, . . . , ’H’} bzw .<br />
52 ∗ { ’A’ , . . . , g2 −1, g2+1, . . . , g1 −1, g1+1, . . . , ’H ’ }.<br />
53 ∗ Entsprechend muss das vom Zufallsgenerator erhaltene Zeichen<br />
54 ∗ um 1 erhoeht werden fuer den Bereich zwischen min(g1 , g2) <strong>und</strong><br />
55 ∗ max(g1 , g2) − 2 ( jeweils einschli esslich ) <strong>und</strong> um 2 erhoeht<br />
56 ∗ werden fuer den Bereich ab max(g1 , g2) − 1.<br />
57 ∗/<br />
58<br />
59 // kleinstesG = min(g1 , g2) <strong>und</strong> groesstesG = max(g1 , g2)<br />
60 int kleinstesG , groesstesG ;<br />
61 if (g2 >= g1) {<br />
62 kleinstesG = g1 ;<br />
63 groesstesG = g2 ;<br />
64 }<br />
65 else {<br />
66 kleinstesG = g2 ;<br />
67 groesstesG = g1 ;<br />
68 }<br />
69<br />
70 g3 = Zufall .zufallszeichen ( ’F ’ ) ;<br />
71 if (g3 >= kleinstesG ) {<br />
72 ++g3 ;<br />
73 }<br />
74 if (g3 >= groesstesG ) {<br />
75 ++g3 ;<br />
76 }<br />
77<br />
78 /∗ Das Vorgehen fuer das vierte Zeichen is t nun aehnlich dem Vorgehen<br />
79 ∗ fuer das dritte Zeichen . Hier wird zunaechst ein Zeichen aus dem<br />
80 ∗ Wertebereich { ’A’ , . . . , ’E’} gewaehlt . Die moeglichen Zeichen sind<br />
81 ∗ dann diejenigen aus der Menge { ’A’ , . . . , ’H’} \ {g1 , g2 , g3 }.<br />
82 ∗<br />
83 ∗ Hierfuer s o l l gelten :<br />
84 ∗ {kleinstesG , mittleresG , groesstesG } == {g1 , g2 , g3 } , wobei<br />
85 ∗ kleinstesG = min(g1 , g2 , g3 ) , groesstesG = max(g1 , g2 , g3) <strong>und</strong><br />
86 ∗ kleinstesG < mittleresG < groesstesG<br />
87 ∗/<br />
88<br />
89 int mittleresG ;<br />
90 if (g3 > kleinstesG ) {<br />
91 if (g3 > groesstesG ) {<br />
92 mittleresG = groesstesG ;<br />
93 groesstesG = g3 ;<br />
94 }<br />
95 else {<br />
96 mittleresG = g3 ;<br />
97 }
98 }<br />
99 else {<br />
100 mittleresG = kleinstesG ;<br />
101 kleinstesG = g3 ;<br />
102 }<br />
103<br />
104 g4 = Zufall .zufallszeichen ( ’E ’ ) ;<br />
105 if (g4 >= kleinstesG ) {<br />
106 ++g4 ;<br />
107 }<br />
108 if (g4 >= mittleresG ) {<br />
109 ++g4 ;<br />
110 }<br />
111 if (g4 >= groesstesG ) {<br />
112 ++g4 ;<br />
113 }<br />
114<br />
115<br />
116 /∗ Die folgende Schleife i s t die in der Aufgabenstellung geforderte<br />
117 ∗ do−while −Schleife .<br />
118 ∗/<br />
119 do {<br />
120<br />
121 /∗ Speichert , ob die Eingabe genau vier Zeichen aus dem erlaubten<br />
122 ∗ Alphabet enthaelt<br />
123 ∗/<br />
124 boolean korrekteEingabe ;<br />
125<br />
126 /∗ Die folgende do−while −Schleife i s t fuer die Eingabe zustaendig .<br />
127 ∗ Der Benutzer muss genau vier Zeichen eingeben .<br />
128 ∗ Ansonsten wird er zur erneuten Eingabe aufgefordert .<br />
129 ∗ Gleichzeitig wird das eingegebene Wort in seine Zeichen z erlegt .<br />
130 ∗/<br />
131 do {<br />
132 korrekteEingabe = true ;<br />
133 System .out .println (” Bitte geben Sie ein Wort aus vier Zeichen aus”<br />
134 + ” { ’A ’ , ’B ’ , . . . , ’H’} ein ! ” ) ;<br />
135 eingabe = IO .readLine ( ) ;<br />
136<br />
137 // Laenge der Eingabe ueberpruefen<br />
138 if (IO .length (eingabe ) != 4) {<br />
139 System .out .println (” Bitte geben Sie genau vier Zeichen ein ! ” ) ;<br />
140 korrekteEingabe = false ;<br />
141 }<br />
142 else {<br />
143 // ueberpruefen , ob die Eingabe nur erlaubte Zeichen enthaelt<br />
144 for ( int i = 0; i < 4; ++i) {<br />
145 char itesZeichenDerEingabe = IO .charAt (eingabe , i ) ;<br />
146 if ( ! (itesZeichenDerEingabe >= ’A’<br />
147 && itesZeichenDerEingabe
148 System .out . println (” Bitte geben Sie nur Zeichen aus”<br />
149 + ” { ’A ’ , ’B ’ , . . . , ’H’} ein ! ” ) ;<br />
150 korrekteEingabe = false ;<br />
151 break ;<br />
152 }<br />
153 }<br />
154 }<br />
155 }<br />
156 while ( ! korrekteEingabe ) ;<br />
157<br />
158 e1 = IO .charAt (eingabe , 0);<br />
159 e2 = IO .charAt (eingabe , 1);<br />
160 e3 = IO .charAt (eingabe , 2);<br />
161 e4 = IO .charAt (eingabe , 3);<br />
162<br />
163 /∗ In der Variable richtigeStellen wird die Anzahl der an der<br />
164 ∗ richtigen S telle geratenen Zeichen berechnet .<br />
165 ∗/<br />
166 int richtigeStellen = 0;<br />
167<br />
168 if (e1 == g1 ) {<br />
169 ++richtigeStellen ;<br />
170 }<br />
171 if (e2 == g2 ) {<br />
172 ++richtigeStellen ;<br />
173 }<br />
174 if (e3 == g3 ) {<br />
175 ++richtigeStellen ;<br />
176 }<br />
177 if (e4 == g4 ) {<br />
178 ++richtigeStellen ;<br />
179 }<br />
180<br />
181 System .out .println (” Richtige S tellen : ” + richtigeStellen );<br />
182<br />
183 /∗ In der Variable vorkommende wird die Anzahl der geratenen<br />
184 ∗ Zeichen berechnet , die zwar im Geheimwort auftreten ,<br />
185 ∗ jedoch nicht an der geratenen S telle .<br />
186 ∗/<br />
187 int vorkommende = 0;<br />
188<br />
189 if (e1 == g2 | | e1 == g3 | | e1 == g4 ) {<br />
190 ++vorkommende ;<br />
191 }<br />
192 if (e2 == g1 | | e2 == g3 | | e2 == g4 ) {<br />
193 ++vorkommende ;<br />
194 }<br />
195 if (e3 == g1 | | e3 == g2 | | e3 == g4 ) {<br />
196 ++vorkommende ;<br />
197 }
198 if (e4 == g1 | | e4 == g2 | | e4 == g3 ) {<br />
199 ++vorkommende ;<br />
200 }<br />
201<br />
202 System .out .println (”Auftretende Zeichen : ” + vorkommende ) ;<br />
203<br />
204 /∗ Wenn alle Zeichen r ichtig <strong>und</strong> jeweils an der richtigen St elle<br />
205 ∗ geraten wurden , dann hat der Benutzer das Geheimwort erraten .<br />
206 ∗ Die Schleife wird verlassen .<br />
207 ∗/<br />
208 if (richtigeStellen == 4) {<br />
209 break ;<br />
210 }<br />
211<br />
212 // Die Nummer des Rateversuchs wird um 1 erhoeht .<br />
213 ++j ;<br />
214 }<br />
215 // Der Benutzer darf zwoelfmal raten .<br />
216 while (j
Aufgabe 4<br />
a) 〈n ≥ 0〉<br />
〈n ≥ 0 ∧ 0 = 0〉<br />
i = 0;<br />
〈n ≥ 0 ∧ i = 0〉<br />
〈n ≥ 0 ∧ i = 0 ∧ 0 = 0〉<br />
res = 0;<br />
〈n ≥ 0 ∧ i = 0 ∧ res = 0〉<br />
〈i ≤ n ∧ res = n ∗ i〉<br />
while (i < n) {<br />
〈i ≤ n ∧ res = n ∗ i ∧ i < n〉<br />
〈i < n ∧ res + n = n ∗ i + n〉<br />
res = res + n;<br />
〈i < n ∧ res = n ∗ i + n〉<br />
〈i + 1 ≤ n ∧ res = n ∗ (i + 1)〉<br />
i = i + 1;<br />
〈i ≤ n ∧ res = n ∗ i〉<br />
}<br />
〈i ≤ n ∧ res = n ∗ i ∧ i ≮ n〉<br />
〈res = n 2 〉
) Eine Variante ist V = n − i, denn aus der Schleifenbedingung i < n folgt<br />
n − i ≥ 0. Somit:<br />
res = res + n;<br />
i = i + 1;<br />
〈n − i = m ∧ i < n〉<br />
〈n − (i + 1) < m〉<br />
〈n − (i + 1) < m〉<br />
〈n − i < m〉<br />
Damit ist die Terminierung der einzigen Schleife in P gezeigt.<br />
c) Für n = 46341 nimmt die int-Variable res einen negativen Wert an. Der<br />
Gr<strong>und</strong> dafür ist, dass das eigentlich erwünschte Ergebnis 46341 2 = 2147488281<br />
größer ist als der maximal in einem int darstellbare Wert von 2 31 − 1. Bei der<br />
obigen Verifikation gehen wir jedoch vereinfachend davon aus, dass beliebig<br />
große ganze Zahlen dargestellt werden können.