Verschachtelte Schleifen Aufgabe Schreiben Sie ein Programm das
Verschachtelte Schleifen
Aufgabe: Schreiben Sie ein Programm, das die folgende, hellblau gekennzeichnete Multiplikationstabelle erstellt.
Die oberste Zeile wird jeweils multipliziert mit: * 1 2 3 4 . . . 10 1 1 1 2 3 4 . . . 10 2 2 2 4 6 8 . . . 20 3 3 3 6 9 12 . . . 30 4 4 4 8 12 16 . . . 40 . . . . 10 10 20 30 40 . . . 100
Programmier-Idee:
ausgabe_zeile_ 1 das bedeutet konkret die Ausgabe: 1· 1, 1· 2, 1· 3, . . . , 1· 10 ausgabe_zeile_ 2 das bedeutet konkret die Ausgabe: 2· 1, 2· 2, 2· 3, . . . , 2· 10 . . . Wie kann man dies mit welcher Anweisung durch ein Struktogramm auch noch kompakter (kürzer) darstellen ? ausgabe_zeile_ 10 das bedeutet konkret die Ausgabe: 10· 1, 10· 2, 10· 3, . . . , 10· 10
for(i=1; i<=10; i++) ausgabe_zeile_ i das bedeutet konkret die Ausgabe: i· 1, i· 2, i· 3, . . . , i· 10 zeilenumbruch Oder anders dargestellt: Bemerkung: i++ bedeutet dasselbe wie i=i+1
for(i=1; i<=10; i++) ausgabe(i· 1), ausgabe(i· 2), ausgabe(i· 3), . . . , ausgabe(i· 10) zeilenumbruch Wie kann man diese Anweisungen mit welcher Anweisung durch ein Struktogramm auch noch kompakter (kürzer) darstellen ?
for(i=1; i<=10; i++) for(j=1; j<=10; j++) ausgabe(i*j) zeilenumbruch
umgesetzt in C ergibt dies:
int main(){ int i, j, erg; for(i=1; i<=10; i++){ for(j=1; j<=10; j++){ erg=i*j; printf("%d ", erg); } printf("n"); } }
Wir gehen das Programm Schritt für Schritt durch. . . Um uns nicht zu langweilen und nicht zu viel Zeit zu verbrauchen, werden wir i und j nicht bis 10, sondern nur jeweils bis 2 hochzählen. Die Bildschirmausgabe wird mit gelber Farbe angezeigt
int main(){ 1 1 wahr int i, j, erg; for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); } erg ? ? printf("n"); }i ? 1 } j ? ?
int main(){ 1 wahr int i, j, erg; 1 for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); } erg ? ? ? printf("n"); }i ? 1 1 } j ? ? 1
int main(){ int i, j, erg; for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); } erg ? ? ? 1 printf("n"); }i ? 1 1 1 } j ? ? 11
int main(){ int i, j, erg; for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); 1 } erg ? ? ? 1 printf("n"); }i ? 1 1 1 } j ? ? 11
int main(){ wahr 2 int i, j, erg; 2 for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); 1 } erg ? ? ? 1 1 printf("n"); }i ? 1 1 } j ? ? 11 2
int main(){ int i, j, erg; for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); 1 } erg ? ? ? 1 1 2 printf("n"); }i ? 1 1 1 } j ? ? 11 22
int main(){ int i, j, erg; for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); 1 2 } erg ? ? ? 1 1 2 printf("n"); }i ? 1 1 1 } j ? ? 11 22
int main(){ 3 falsch int i, j, erg; 3 for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); 1 2 } erg ? ? ? 1 1 2 2 printf("n"); }i ? 1 1 1 } j ? ? 11 223
veranlaßt Zeilenumbruch: int main(){ Kursor steht jetzt hier! int i, j, erg; for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); 1 2 } erg ? ? ? 1 1 2 2 printf("n"); }i ? 1 1 1 } j ? ? 11 223
int main(){ 2 2 wahr int i, j, erg; for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); 1 2 } erg ? ? ? 1 1 2 2 2 printf("n"); }i ? 1 1 1 2 } j ? ? 11 2233
int main(){ 1 wahr int i, j, erg; 1 for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); 1 2 } erg ? ? ? 1 1 2 2 printf("n"); }i ? 1 1 1 2 2 } j ? ? 11 22331
int main(){ int i, j, erg; for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); 1 2 } erg ? ? ? 1 1 2 2 2 printf("n"); }i ? 1 1 1 2 2 2 } j ? ? 11 223311
int main(){ int i, j, erg; for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); 1 2 } erg ? ? ? 1 1 2 2 2 printf("n"); }i ? 1 1 1 2 2 2 } j ? ? 11 223311
int main(){ wahr 2 int i, j, erg; 2 for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); 1 2 } erg ? ? ? 1 1 2 2 2 2 printf("n"); }i ? 1 1 1 2 2 } j ? ? 11 2233112
int main(){ int i, j, erg; for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); 1 2 } erg ? ? ? 1 1 2 2 2 4 2 printf("n"); }i ? 1 1 1 2 2 2 } j ? ? 11 22331122
int main(){ int i, j, erg; for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); 1 2 2 4 } erg ? ? ? 1 1 2 2 2 4 printf("n"); }i ? 1 1 1 2 2 2 } j ? ? 11 22331122
int main(){ 3 falsch int i, j, erg; 3 for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); 1 2 2 4 } erg ? ? ? 1 1 2 2 2 4 4 printf("n"); }i ? 1 1 1 2 2 2 } j ? ? 11 223311223
veranlaßt Zeilenumbruch: int main(){ Kursor steht jetzt hier! int i, j, erg; for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); 1 2 2 4 } erg ? ? ? 1 1 2 2 2 4 4 printf("n"); }i ? 1 1 1 2 2 2 } j ? ? 11 223311223
int main(){ 3 3 falsch int i, j, erg; for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); 1 2 2 4 } erg ? ? ? 1 1 2 2 2 4 4 4 printf("n"); }i ? 1 1 1 2 2 2 3 } j ? ? 11 2233112333
aus Platzgründen fehlt hier int main(){ noch das return, das int i, j, erg; Programm beendet. for(i=1; i<=2; i++){ for(j=1; j<=2; j++){ erg=i*j; printf("%d ", erg); 1 2 2 4 } erg ? ? ? 1 1 2 2 2 4 4 4 printf("n"); }i ? 1 1 1 2 2 2 3 } j ? ? 11 2233112333
0#0#0 Aufgabe: 0#0#1 Erstellen Sie ein 0#0#2 Programm, das die Zahlen von 0 bis 999. . . in der Form (siehe 9#9#7 rechts) auf dem 9#9#8 Bildschirm ausgibt: 9#9#9
Vorbemerkungen:
ausgabe_zeile_i#j#k ist Abkürzung für die Ausgabe der Zeile, die an der 1. Spalte den Wert i, an der 2. Spalte den Wert j und an der 3. Spalte den Wert k hat, also: i#j#k
Beispiel: ausgabe_zeile_6#3#8
ausgabe_zeile_i#j ist Abkürzung für die Ausgabe aller Zeilen, die an der 1. Spalte den Wert i und der 2. Spalte den Wert j haben, also:
i#j#0 i#j#1. . . i#j#8 i#j#9
Beispiel: ausgabe_zeile_5#7 5#7#0 5#7#1 5#7#2. . . 5#7#8 5#7#9
ausgabe_zeile_i ist Abkürzung für die Ausgabe aller Zeilen, die an der 1. Spalte den Wert i haben, also:
i#0#0 i#0#1. . . i#9#8 i#9#9
Beispiel: ausgabe_zeile_3 3#0#0 3#0#1 3#0#2. . . 3#9#8 3#9#9
Programmier-Idee
ausgabe_zeile_0 ausgabe_zeile_1 ausgabe_zeile_2 ausgabe_zeile_3 ausgabe_zeile_4 ausgabe_zeile_5 ausgabe_zeile_6 ausgabe_zeile_7 ausgabe_zeile_8 ausgabe_zeile_9 Wie kann man dies mit welcher Anweisung durch ein Struktogramm auch noch kompakter (kürzer) darstellen ?
for(i=0; i<10; i++) ausgabe_zeile_ i das bedeutet konkret die Ausgabe: i#0#0 i#0#1 i#0#2. . . i#9#8 i#9#9 oder systematischer dargestellt:
for(i=0; i<10; i++) i#0#0 i#0#1 i#0#2. . . i#0#7 i#0#8 i#0#9 i#1#0 i#1#1 i#1#2. . . i#1#7 i#1#8 i#1#9 i#2#0 i#8#0 i#9#0 i#2#1 i#8#1 i#9#1 i#2#2 i#8#2 i#9#2. . . i#2#7 i#8#7 i#9#7 i#2#8 i#8#8 i#9#8 i#2#9 i#8#9 i#9#9 Wie kann man dies mit welcher Anweisung durch ein Struktogramm auch noch kompakter (kürzer) darstellen ? Jeder Block kommt jeweils untereinander (aus Platzgründen hier nebeneinander dargestellt)
for(i=0; i<10; i++) ausgabe_zeile_i#0 ausgabe_zeile_i#1 ausgabe_zeile_i#2. . . ausgabe_zeile_i#8 ausgabe_zeile_i#9
for(i=0; i<10; i++) for(j=0; j<10; j++) ausgabe_zeile_i#j Oder anders dargestellt:
for(i=0; i<10; i++) for(j=0; j<10; j++)
for(i=0; i<10; i++) for(j=0; j<10; j++) ausgabe_zeile_i#j#0 ausgabe_zeile_i#j#1. . . ausgabe_zeile_i#j#9 Wie kann man dies mit welcher Anweisung durch ein Struktogramm auch noch kompakter (kürzer) darstellen ?
for(i=0; i<10; i++) for(j=0; j<10; j++)
for(i=0; i<10; i++) for(j=0; j<10; j++) for(k=0; k<10; k++) ausgabe_zeile_i#j#k
umgesetzt in C ergibt dies:
int main(){ int i, j, k; for(i=0; i<10; i++){ for(j=0; j<10; j++){ for(k=0; k<10; k++){ printf("%d#%d# %dn", i, j, k); } }
Wichtige Bemerkung: In der innersten Schleife durchläuft die Zahlenkombination i, j, k alle möglichen Werte, also
durchläuft alle Werte von 0 bis 9 i j k also: durchläuft alle Werte von 0 bis 9
von: 0 0 0
bis: 9 9 9
Angenommen, man fasst das Gebilde unten als einen 3 -stelligen Tachometer auf, der aus den 3 Rädchen i, j und k besteht. Welches Rad dreht sich am schnellsten, welches am langsamsten ? i j k k dreht sich am schnellsten, j dreht sich etwas langsamer und i drehst sich am langsamsten.
Wie kann man die Anzahl der Schleifendurchgänge berechnen ?
10*10*10 Werte für j Werte für i 10*10 0 10 10 0. . 9 1 10*10. . 10 10 0. . 9 0. . . 9. . 0. . . 9 Werte für k 9 10 . . 0. . . 10 9 0. . . 9. . . 0. . . 9
Aufgabe (Zahlenrätsel): gleiche Buchstaben - gleiche Ziffern, verschiedene Buchstaben - verschiedene Ziffern send + more -----money
Wie versuchen durch "Probieren" eine Lösung zu bekommen. . . 1 2 3 4 send 5 6 7 2 + more -----5 6 3 2 8 money Ist diese Lösung korrekt? Nein, denn. . . 1234 + 5672 56328
Hinweis zur Lösung: Systematisch alle möglichen Zahlenkombinationen von s, e, n, d, m, o, r, y ausprobieren und jeweils nachprüfen, ob gilt: send + more = money
Frage: Durch welches Konstrukt bekommt man systematisch alle möglichen Zahlenkombinationen von s, e, n, d, m, o, r, y
Antwort: Durch eine 8 -fach verschachtelte Schleife !
for(s=0; s<10; s++) for(e=0; e<10; e++) for(n=0; n<10; n++) for(d=0; d<10; d++) for(m=0; m<10; m++) for(o=0; o<10; o++) for(r=0; r<10; r++) for(y=0; y<10; y++) was heißt das genau ? erg 1=s*1000+e*100+n*10+d*1 + m*1000+o*100+ r*10+e*1 erg 2=m*10000+o*1000+n*100+e*10+y*1 erg 1==erg 2 w f Buchst. verschieden w f Ausgabe(s, e, n, d, m, o, r, y)
Die Werte der Variablen: s, e, n, d, m, o, r, y sind alle verschieden. Dies bedeutet konkret:
s e s n s d s m s o s r s y e n e d e m e o e r e y n d n m n o n r n y d m d o d r d y m o m r m y o r o y r y
umgesetzt in C ergibt dies:
int main(){ int s, e, n, d, m, o, r, y; int erg 1, erg 2, erg 3; for (s=0; s<=9; s++){ schliessende Klammern for (e=0; e<=9; e++){ mussten aus Platzgründen for (n=0; n<=9; n++){ leider weggelassen werden for (d=0; d<=9; d++){ for (m=0; m<=9; m++){ for (o=0; o<=9; o++){ for (r=0; r<=9; r++){ for (y=0; y<=9; y++){ erg 1=s*1000+e*100+n*10+d*1+m*1000+o*100+r*10+e*1; erg 2 = m*10000 + o*1000 + n*100 + e*10 + y*1; if(erg 1 == erg 2){ erg 3=s!=e && s!=n && s!=d && s!=m && s!=o && s!=r && s!=y && e!=n && e!=d && e!=m && e!=o && e!=r && e!=y && n!=d && n!=m && n!=o && n!=r && n!=y && d!=m && d!=o && d!=r && d!=y && m!=o && m!=r && m!=y && o!=r && o!=y && r!=y; if(erg 3!=0){ printf(" %d %dn", s, e, n, d); printf(" %d %dn", m, o, r, e); printf("%d %d %dnn", m, o, n, e, y);
Frage (Rechenzeit): Wieviel Zahlenkombinationen der Variablen s, e, n, d, m, o, r, y gibt es ?
durchläuft jeweils alle Werte von 0 bis 9 s e n d m o r y Anzahl der Zahlenkombinationen ist 8 also (siehe vorher): 10
Frage: Wie viele Möglichkeiten kann es maximal bei dieser Art von Zahlenrätseln geben?
Wie viele verschiedene Buchstaben kann es in so einem Zahlenrätsel maximal geben?
Nur 10, weil es ja nur 10 verschiedene Ziffern geben kann.
Also kann es maximal nur 10 10 verschiedene Möglichkeiten geben.
Überlegungen zur Rechenzeit
Annahme: best case, d. h. wir nehmen den besten Fall an:
-2 Ghz Taktfrequenz - Eine Berechnung pro Takt - Alle Daten befinden sich im Prozessorcache (L 1 -Cache). Es muß also nicht über einen (langsamen) Bus auf den Arbeitsspeicher zugegriffen werden, sondern die Daten können mit dem vollen Prozessortakt angesprochen werden.
Was bedeutet 2 Ghz Taktfrequenz?
Wie viel Zeit braucht er dann für einen Takt? 2* 9 10 Takte pro Sekunde
Wie viel Zeit braucht er dann für 1010 Rechnungen (bei den o. g. Voraussetzungen)? 1 T = ------ s 9 2 * 10
t=T* 10 10 1 10 = ------ s * 10 9 2 * 10 10 10 = ------ s = 5 s 9 2 * 10
In dieser best-case. Modellrechnung braucht der Prozessor also 5 Sekunden. Die Modellrechnung setzt kein paralleles Rechnen voraus.
Die Methode sämtliche Möglichkeiten zu testen, nennt man auch. Brute Force
Wo wird Brute Force noch benutzt ?
Programme, die Passwörter ermitteln sollen
- Slides: 87