TECHNISCHE UNIVERSITÄT MÜNCHEN FAKULTÄT FÜR INFORMATIK Lehrstuhl für Sprachen und Beschreibungsstrukturen Einführung in die Informatik I Prof. Dr. Helmut Seidl, M. Schwarz, A. Herz, Dr. M. Petter WS 11/12 Übungsblatt 4 10.11.10 Abgabe: 21.11.10 (vor 12 Uhr) Aufgabe 4.1 (P) Arrays verstehen Diskutieren Sie, was in dem folgenden Programm passiert. 1 public c l a s s MeineArrays extends MiniJava { 2 public s t a t i c void main ( S t r i n g [ ] a r g s ) { 3 4 int [ ] e r s t e s A = { 1 , 2 , 3 , 4 } ; 5 write ( erstesA [ 1 ] ) ; 6 7 int [ ] z w e i t e s A = new int [ 7 ] ; 8 zweitesA [ 0 ] = 3 ; 9 int i =1; 10 while ( i <z w e i t e s A . l e n g t h ) { 11 z w e i t e s A [ i ] = i +3; 12 i ++; 13 } 14 15 fo r ( int j =0; j <z w e i t e s A . l e n g t h ; j ++) { 16 write ( zweitesA [ j ] ) ; 17 i ++; 18 } 19 20 write ( zweitesA [ i ] ) ; 21 22 zweitesA = erstesA ; 23 zweitesA [ 1 ] = 2 5 ; 24 write ( erstesA [ 1 ] ) ; 25 } 26 } Lösungsvorschlag 4.1 Folgendes passiert in dem Programm: 4 Anlegen eines Arrays mit festem Inhalt 5 Ausgeben des Wertes an Position 1 → 2 (Die Positionen beginnen bei 0.) 7 Anlegen eines leeren Arrays der Länge 7 8 Füllen der Position 0 mit dem Wert 3 11 Füllen der i-ten Position mit i + 3 2 9-13 Das zweite Array ist [3, 4, 5, 6, 7, 8, 9] 15 For-Schleife durchläuft das Array 15-18 Schrittweises Ausgeben des Arrays 17 Variable i wird insgesamt um Länge von Array zweitesA hochgezählt 20 Laufzeitfehler! Position i existiert in Array zweitesA nicht. Es wird eine ArrayIndexOutOfBoundsException geworfen. 22 Die Referenz auf Array erstesA wird in Variable zweitesA kopiert. 23 Das Feld 1 des Arrays, auf das sich zweitesA bezieht, wird auf 25 gesetzt. 24 Durch Zeile 23 wurde auch diese Ausgabe beeinflusst, da erstesA seit Zeile 22 das selbe Array referenziert wie zweitesA. Aufgabe 4.2 (P) Minimum und Maximum Schreiben Sie ein MiniJava-Programm namens MinMax.java, das in einem Array von ganzen Zahlen den kleinsten und den größten Wert findet. Das Programm soll sich wie folgt verhalten: • Zunächst fragt das Programm ab, wie viele Zahlen in das Array eingegeben werden sollen. • Dann werden die Zahlen eingegeben und in einem Array gespeichert. • Anschließend wird das Array durchsucht und in einem Durchgang soll sowohl die kleinste als auch die größte Zahl gefunden werden. • Schließlich sollen die kleinste und die größte Zahl ausgegeben werden. Lösungsvorschlag 4.2 public c l a s s MinMax extends MiniJava { public s t a t i c void main ( S t r i n g [ ] a r g s ) { // Anzahl d e r e i n z u g e b e n d e n Zahlen a b f r a g e n int e i n g a b e n = r e a d I n t ( ”Wie v i e l e Zahlen m c h t e n S i e e i n g e b e n ? ” ); i f ( eingaben < 1) { return ; } // Array a n l e g e n int [ ] z a h l e n = new int [ e i n g a b e n ] ; // Array mit Zahlen f l l e n int z a h l ; int i = 0 ; while ( i < e i n g a b e n ) { z a h l = r e a d I n t ( ” B i t t e geben S i e d i e ” + ( i + 1 ) + ” . Zahl e i n . ”) ; 3 zahlen [ i ] = zahl ; i ++; } // min und max b e r e c h n e n int min = z a h l e n [ 0 ] ; int max = z a h l e n [ 0 ] ; i = 1; while ( i < e i n g a b e n ) { i f ( z a h l e n [ i ] < min ) { min = z a h l e n [ i ] ; } i f ( z a h l e n [ i ] > max) { max = z a h l e n [ i ] ; } i ++; } // Ausgeben w r i t e ( ”Die k l e i n s t e Zahl war ” + min ) ; w r i t e ( ”Die g r t e Zahl war ” + max) ; } } Aufgabe 4.3 (P) Addition von Arrays Schreiben Sie ein MiniJava-Programm namens Add.java, 9 5 1 5 welches zwei positive Zahlen einliest und diese in int- a1 : Arrays a1 der Länge m und a2 der Länge n stellenweise ein- a2 : + 7 1 6 fügt. Ein Arrayelement soll hierbei nur die Ziffern 0, 1, . . . , 9 beinhalten. (ints können maximal 10 Dezimalstellen ha- a : 1 0 2 3 1 3 ben.) Anschließend werden die beiden Arrays addiert (wie beim schriftlichen Addieren aus der Schule) und das Ergebnis dieser Addition wird in ein Array a3 der Länge max(m, n) + 1 abgespeichert. Dann soll das Ergebnisarray a3 mit Hilfe der Methode java.util.Arrays.toString(a3 ) in einen String verwandelt und ausgegeben werden. Lösungsvorschlag 4.3 public c l a s s Add extends MiniJava { public s t a t i c void main ( S t r i n g [ ] a r g s ) { int i 1 = r e a d ( ) ; int i 2 = r e a d ( ) ; // 11 S t e l l e n r e i c h e n l o c k e r f u e r 32 b i t −i n t s int [ ] a1 = new int [ 1 1 ] ; int [ ] a2 = new int [ 1 1 ] ; // 12 S t e l l e n wegen U e b e r t r a g ! int [ ] a3 = new int [ 1 2 ] ; 4 // Z u e r s t Eingabe i n Arrays v e r w a n d e l n ! // dazu gehen w i r a l l e 10 er−S t e l l e n durch : int i =0; while ( i 1 >0 | | i 2 >0){ a1 [ i ]= i 1 %10; a2 [ i ]= i 2 %10; i 1=i 1 / 1 0 ; i 2=i 2 / 1 0 ; i ++; } int u e b e r t r a g =0; fo r ( int j =0; j <11; j ++){ // S t e l l e n und den l e t z t e n U e b e r t r a g aufsummieren int summe = a1 [ j ]+ a2 [ j ]+ u e b e r t r a g ; // a l l e 10 e r i n den U e b e r t r a g u e b e r t r a g=summe / 1 0 ; // a l l e 1 e r i n d i e r i c h t i g e S t e l l e a3 [ j ]= summe%10; } // l e t z t e n U e b e r t r a g n i c h t v e r g e s s e n a3 [ 1 1 ] = u e b e r t r a g ; // K o n v e r t i e r u n g und Ausgabe d e r Menge r e s u l t S t r i n g e r g e b n i s = j a v a . u t i l . Arrays . t o S t r i n g ( a3 ) ; write ( ergebnis ) ; } } Aufgabe 4.4 [4 Punkte] (H) Sieb des Eratosthenes Folgendes Verfahren zur Primzahlen-Gewinnung ist als Sieb des Eratosthenes bekannt: Aus der Menge der natürlichen Zahlen von 2 bis n werden alle Nicht-Primzahlen gestrichen. Beginne mit der Zahl 2 und streiche alle echten Vielfachen von 2. Streiche nun sukzessiv alle echten Vielfachen der jeweils nächsthöheren noch nicht gestrichenen Zahl. Nach Streichung aller Vielfachen enthält die Restmenge nur noch Primzahlen. Implementieren Sie das oben beschriebene Verfahren in Java mit Hilfe eines Arrays. Ihr Programm soll nach Festlegung einer Obergrenze durch den Benutzer alle Primzahlen bis zu dieser Grenze bestimmen und ausgeben. Lösungsvorschlag 4.4 public c l a s s E r a t o s t h e n e s extends MiniJava { public s t a t i c void main ( S t r i n g [ ] a r g s ) { // Eingabe int n = r e a d ( ) ; i f (n < 0) { // f e h l e r h a f t e Eingabe w r i t e ( ”Nur p o s i t i v e Eingaben e r l a u b t . ”) ; } else { // k o r r e k t e Eingabe ; Berechnung kann e r f o l g e n 5 // S i e b a n l e g e n boolean prime [ ] = new boolean [ n + 1 ] ; f o r ( int i = 2 ; i < prime . l e n g t h ; i ++) prime [ i ] = true ; // Primzahlen b e r e c h n e n f o r ( int i = 2 ; i < prime . l e n g t h ; i ++) { i f ( prime [ i ] ) { // Primza hl a u s g e b e n System . out . p r i n t l n ( i ) ; // a l l e V i e l f a c h e n s t r e i c h e n f o r ( int j = i ∗ i ; j < prime . l e n g t h ; j = j + i ) { prime [ j ] = f a l s e ; } } } } } } Mögliche Optimierungen: • Nur ungerade Zahlen berücksichtigen • Berechnung bis zur Wurzel der oberen Grenze ist ausreichend Aufgabe 4.5 [6+2 Punkte] (H) Mustererkennung a) Schreiben Sie ein Programm namens Muster.java, das eine aus 0 und 1 Symbolen bestehende Folge mit benutzerdefinierter Länge zufällig generiert und darin die längste Teilfolge bestehend ausschließlich aus 0 Symbolen findet. (Hinweis: Eine binäre Zahl (0 oder 1) kann zufällig mit dem Ausdruck (int)(Math.random()*2) generiert werden) Geben sie die Startposition und die Länge der gefunden Teilfolge aus. b) Ergänzen Sie das Programm Muster.java so, dass die längste Folge von 0 Symbolen in einem aus 0 und 1 Symbolen bestehendes zweidimensionales Array gefunden wird. Erfragen sei die Größe vom Benutzer und generieren sie die Symbole zufällig. Geben sie die Startkoordinaten, die Richtung (waagerecht, senkrecht, diagonal) und die Länge der gefundenen Folge aus. (Bonus) Ergänzen Sie das Programm Muster.java, so, dass in dem zweidimensionalen Array auch das größte Rechteck bestehend nur aus 0 Symbolen (d.h. auch die Fläche besteht nur aus /tt 0en) gefunden wird. Geben sie die Startkoordinaten und die Grösse des gefundenen Rechtecks aus. Lösungsvorschlag 4.5 public c l a s s MusterErkennung extends MiniJava { public s t a t i c void main ( S t r i n g [ ] a r g s ) { int symbol = 0 ; 6 // T e i l a u f g a b e a ) int n = r e a d ( ”Geben S i e d i e Laenge d e r F o l g e e i n : ”) ; int [ ] s e q u e n c e = new int [ n ] ; fo r ( int j = 0 ; j < n ; j ++) { // g e n e r a t e s y m b o l s s e q u e n c e [ j ] = ( int ) ( Math . random ( ) + 0 . 5 ) ; } fo r ( int i = 0 ; i < s e q u e n c e . l e n g t h ; i ++) { // p r i n t System . out . p r i n t ( s e q u e n c e [ i ] ) ; } System . out . p r i n t l n ( ) ; int p = 0 ; int max = 0 , posmax = 0 , pos = 0 ; while ( p < s e q u e n c e . l e n g t h ) { // u e b e r s p r i n g e unpassende Z e i c h e n while ( p < s e q u e n c e . l e n g t h && s e q u e n c e [ p ] != symbol ) { p++; } // merke S t a r t p o s i t i o n d e r Sequenz pos = p ; // s u c h e Ende d e r Sequenz while ( p < s e q u e n c e . l e n g t h && s e q u e n c e [ p ] == symbol ) { p++; } // f a l l s Sequenz l a e n g e r a l s b i s h e r i g e s Maximum , s e t z e neues Maximum i f ( p > pos && p − pos > max) { posmax = pos ; max = p − pos ; } } i f (max > 0 ) { // Ausgabe d e s e r g e b n i s s e s System . out . p r i n t l n ( ”Maximal s e q u e n c e s t a r t s a t ” + posmax + ” and has l e n g t h ” + max + ” . ”) ; } else { System . out . p r i n t l n ( ”No symbol ” + symbol + ” found . ”) ; } // T e i l a u f g a b e b ) int h = r e a d ( ”Geben S i e d i e Hoehe e i n : ”) ; int b = r e a d ( ”Geben S i e d i e B r e i t e e i n : ”) ; int [ ] [ ] s u r f a c e = new int [ h ] [ b ] ; fo r ( int i = 0 ; i < h ; i ++) { // g e n e r a t e s y m b o l s f o r ( int j = 0 ; j < b ; j ++) { s u r f a c e [ i ] [ j ] = ( int ) ( Math . random ( ) + 0 . 5 ) ; } } // o der f e s t e Werte zum Testen : // i n t [ ] [ ] s u r f a c e = {{1 ,0 ,0 ,1 ,1 ,1} ,{0 ,0 ,0 ,0 ,0 ,0} ,{0 ,1 ,0 ,0 ,0 ,1} ,{0 ,1 ,0 ,0 ,0 ,0} ,{1 ,1 ,1 ,0 ,0 ,1} h=6; b =6; // i n t [ ] [ ] { { 1 , 1 , 0 } , { 0 , 0 , 1 } , { 0 , 0 , 0 } } ; h = 3 ; b =3; fo r ( int j = 0 ; j < s u r f a c e . l e n g t h ; j ++) { // p r i n t f o r ( int i = 0 ; i < s u r f a c e [ 0 ] . l e n g t h ; i ++) { System . out . p r i n t ( s u r f a c e [ j ] [ i ] ) ; 7 } System . out . p r i n t l n ( ) ; } int s t e p , maxline =−1, maxx=−1, maxy=−1; S t r i n g d i r = ”” ; fo r ( int j = 0 ; j < h ; j ++) { // i t e r a t e o v e r l i n e s f o r ( int i = 0 ; i < b ; i ++) // i t e r a t e o v e r columns { i f ( s u r f a c e [ j ] [ i ] == symbol ) { // s t a r t l o o k i n g f o r l i n e s from t h e c u r r e n t p o i n t step = 0; while ( s t e p+i < b && s u r f a c e [ j ] [ s t e p+i ] == symbol ) { // w a a a g e r e c h t s t e p ++; } i f ( s t e p > maxline ) { maxline = s t e p ; maxx = i ; maxy = j ; dir = ”horizontally ”; } step = 0; while ( s t e p+j < h && s u r f a c e [ s t e p+j ] [ i ] == symbol ) { // s e n k r e c h t s t e p ++; } i f ( s t e p > maxline ) { maxline = s t e p ; maxx = i ; maxy = j ; dir = ”vertically ”; } step = 0; while ( s t e p+i < b && s t e p+j < h && s u r f a c e [ s t e p+j ] [ s t e p+i ] == symbol ) { // d i a g o n a l von l i n k s oben nach r e c h t s unten s t e p ++; } i f ( s t e p > maxline ) { maxline = s t e p ; maxx = i ; maxy = j ; d i r = ” d i a g o n a l l y ( down ) ” ; } step = 0; while ( i −s t e p >=0 && s t e p+j < h && s u r f a c e [ s t e p+j ] [ i −s t e p ] == symbol ) { // d i a g o n a l von r e c h t s oben nach l i n k s unten s t e p ++; } i f ( s t e p > maxline ) { maxline = s t e p ; maxx = i ; maxy = j ; d i r = ” d i a g o n a l l y ( up ) ” ; } 8 } } } System . out . p r i n t l n ( ”L ongest l i n e s t a r t s a t ( ” + maxx + ” , ” + maxy + ”) , g o e s ” + d i r + ” and has l e n g h t ” + maxline + ” . ”) ; // E r g e b n i s a u s g a b e // Bonusaufgabe : // I d e e n : Bestimme f u e r j e d e P o s i t i o n ( n ,m) das maximale Rechteck , das b e i ( n ,m) b e g i n n t . // Das g r o e s s t e d i e s e r Rechecke i s t dann das g r o e s s t e d e s gesamten F e l d e s . int x , y , xMax = −1, yMax = −1, iMax = −1, jMax = −1; int surfMax = 0 , s u r f ; int i 1 ; fo r ( int j = 0 ; j < h ; j ++) { // i t e r a t e o v e r l i n e s f o r ( int i = 0 ; i < b ; i ++) // i t e r a t e o v e r coulmns { i f ( s u r f a c e [ j ] [ i ] == symbol ) { // s t a r t l o o k i n g f o r r e c t a n g l e s from t h e c u r r e n t point x = i; while ( x < b && s u r f a c e [ j ] [ x ] == symbol ) { // i t e r a t e o v e r t h e p o s s i b l e l e n g t h s ( horizontally ) y = j + 1; while ( y < h ) { // i t e r a t e o v e r p o s s i b l e b r e a d t h s ( vertically ) i1 = i ; // c h e c k i f t h e r e a r e as much s y m b o l s on t h e current l i n e // as t h e c u r r e n t l e n g t h while ( i 1 <= x && s u r f a c e [ y ] [ i 1 ] == symbol ) { i 1 ++; } i f ( i 1 == x + 1 ) // yes , t h e r e a r e ; t r y t h e n e x t row { y++; } e l s e //no , t h e r e aren ’ t ; i t ’ s not a rectangle { break ; } } s u r f = ( x − i + 1 ) ∗ ( y − j ) ; // t h e c u r r e n t surface i f ( s u r f > surfMax ) // a new maximum ; // remember t h e upper l e f t and l o w e r r i g h t corners { surfMax = s u r f ; xMax = x ; yMax = y − 1 ; 9 iMax = i ; jMax = j ; } x++; } } } } System . out . p r i n t l n ( ” L a r g e s t r e c t a n g l e s t a r t s a t ( ” + iMax + ” , ” + jMax + ”) , ends a t ( ” + xMax + ” , ” + yMax + ”) ” + ” and has s u r f a c e ” + surfMax + ” . ”) ; } }