L?sningsforslag ukeoppg. 5:  27. sep - 1. okt (INF1000 - H?st 2010)

Mer om filer (kap 3), tekster (kap. 6), og metoder (kap. 7)
NB! Disse er bare forslag til l?sninger, dine svar kan v?re like gode eller bedre selv om de ser annerledes ut.

M?l
Samle sammen tr?dene med grunnleggende programmering (kap. 1 til 7) f?r vi starter med klasser og objekter neste uke.

Oppgaver til teoritimen

  1. Metode med array som inn-parameter: kap. 7, oppg. 3 (side 134)
    Lag en metode double gjennomsnitt(int[] a) som summerer alle elementene i heltallsarrayen a, og som returnerer (det aritmetiske) gjennomsnittet av verdiene i a.
    // Dette eksemplet viser en annen m?te ? sette opp programmet med bare én klasse.
    // Vi slipper ? bruke to klasser ved ? la objekt-pekeren "gj" referere til
    // den samme klassen som den selv og main-metoden er plassert i.
    class Gjennomsnitt {
    
        public static void main(String[] args) {
    	Gjennomsnitt gj = new Gjennomsnitt();
    	gj.testGjennomsnitt();
        }
    
        void testGjennomsnitt() {
    	int[] a = { 1, 2, 2, 1, 0, 3 };
    	double snitt = gjennomsnitt(a); // Argument: arraynavnet uten klammer
    	System.out.println("Gjennomsnittet er: " + snitt);
        }
    
        double gjennomsnitt(int[] a) {
    	int sum = 0;
    	for (int i = 0; i < a.length; i++) {
    	    sum += a[i];
    	}
    	return (double) sum / a.length;
        }
    }
    
    KJ?REEKSEMPEL:
    Gjennomsnittet er: 1.5
    


  2. Lese to arrayer fra fil:  kap. 5, oppg. 3 (side 97)
    Lag et program som skal behandle data om vekten til elevene i en skoleklasse.  Det er 27 elever i klassen.  Dataene ligger p? fil slik:
    Jens 52
    Marit 43
    ...
    
    (a) Les dataene inn i to arrayer: en navnearray (String) og en vektarray (int).  Hint: Se "// Fil til array" p? side 60 i l?reboka.
    (b) La programmet finne h?yeste og laveste vekt og skrive ut navn og vekt p? disse.
    (c) La programmet beregne gjennomsnittsvekten i klassen.  Hint: Bruk gjennomsnitts-metoden fra oppgave nr. 1 ovenfor.
    import easyIO.*;
    
    class ElevVekt {
        public static void main(String[] args) {
    	In innfil = new In("elevvekt.txt");
    	final int ANT_ELEVER = 27;
    	String[] navn = new String[ANT_ELEVER];
    	int[] vekt = new int[ANT_ELEVER];
    
    	// (a): Leser dataene fra fil inn i to arrayer:
    	for (int i = 0; i < ANT_ELEVER; i++) {
    	    navn[i] = innfil.inWord();
    	    vekt[i] = innfil.inInt();
    	}
    
    	// (b): Finner indeksene i arrayen der vekt er h?yest og lavest:
    	int h?yVektIndeks = 0;
    	int lavVektIndeks = 0;
    	for (int i = 0; i < vekt.length; i++) {
    	    if (vekt[i] > vekt[h?yVektIndeks]) {
    		h?yVektIndeks = i;
    	    }
    	    if (vekt[i] < vekt[lavVektIndeks]) {
    		lavVektIndeks = i;
    	    }
    	}
    	System.out.println("Tyngste elev: " + navn[h?yVektIndeks] + " "
    			   + vekt[h?yVektIndeks] + " kg");
    	System.out.println("Letteste elev: " + navn[lavVektIndeks] + " "
    			   + vekt[lavVektIndeks] + " kg");
    
    	// (c): Gjennomsnittsvekt:
    	ElevVekt ev = new ElevVekt();
    	double snitt = ev.finnGjennomsnitt(vekt);
    	System.out.printf("Gjennomsnittsvekt: %.1f\n", snitt);
    
        }
    
        double finnGjennomsnitt(int[] a) {
    	int sum = 0;
    	for (int i = 0; i < a.length; i++) {
    	    sum += a[i];
    	}
    	return (double) sum / a.length;
        }
    }
    
    KJ?REEKSEMPEL:
    Tyngste elev: Jens 53 kg
    Letteste elev: Anna 33 kg
    Gjennomsnittsvekt: 44.8
    


  3. Tekster: Hva blir skrevet ut? 
    import easyIO.*;
    class Tekster {
        public static void main(String[] args) {
    	 Out skjerm = new Out();
    
    	 String s1 = "hei";
    	 String s2 = "Java";
    	 String[] navn = { "Rune", "Martin", "", "Guro" };
    
    /* a */  skjerm.outln(navn.length + s1.length());
    
    7
    
    /* b */  skjerm.outln(3.1415 + "" + 'x');
    
    
    3.1415x
    /* c */  skjerm.outln("" + false);
    
    
    false
    /* d */  skjerm.outln("" + ! "abc".equals("abc"));
    
    
    false
    /* e */  skjerm.outln("heia" == (s1 + "a"));
    
    
    false
    /* f */  skjerm.outln("heia".equals(s1 + s2.charAt(1)));
    
    
    true
    /* g */  skjerm.outln(s1.equals("h" + navn[0].charAt(3) + 'i'));
    
    
    true
    /* h */  skjerm.outln(navn[1].substring(1));
    
    
    artin
    /* i */  skjerm.outln(navn[1].substring(1, 4));
    
    
    art
    /* j */  skjerm.outln(s2.replace('a', 'i'));
    
    
    Jivi
    /* k */  skjerm.outln(navn[1].indexOf("tin"));
    
    
    3
    /* l */  skjerm.outln(navn[2].indexOf("tin"));
    
    
    -1
    /* m */  skjerm.outln("A".compareTo("A"));
    
    
    0
    /* n */  if (s1.compareTo("zz") < 0) skjerm.outln("s1 alfabetisk foran");  
    
    
    s1 alfabetisk foran
    /* o */  skjerm.outln(navn[3].toUpperCase());
    
    
    GURO
    /* p */  if ("hei p? deg".startsWith(s1)) { skjerm.outln("ja"); }
    
    
    ja
    /* q */  int x = Integer.parseInt("123"); skjerm.outln(x + 1);
    
        }
    }
    
    124


  4. Ord baklengs:  kap. 6, oppg. 3(a-b), (side 115)
    (a) Lag et program som skriver ut teksten ?Agnes i senga? baklengs.  Hint: Bruk en for-l?kke som teller nedover.
    (b) Modifiser programmet over slik at det f?rst gj?r om teksten til kun ? inneholde sm? bokstaver.
    import easyIO.*;
    
    class Baklengs {
        public static void main (String[] args) {
            Out skjerm = new Out();
    
    	String tekst = "Agnes i senga";
    
    	skjerm.out(tekst + " baklengs: ");
    	int antallTegn = tekst.length();
    	for (int i = antallTegn - 1; i >= 0; i--) {
    	    skjerm.out(tekst.charAt(i));
    	}
    	skjerm.outln();
        }
    }
    
    KJ?REEKSEMPEL:
    > java Baklengs
    Agnes i senga baklengs: agnes i sengA
    


  5. Mer om metoder
    Fullf?r f?lgende program, som viser bruk av metoder.  Angi ogs? hva programmet skriver ut.
    import java.util.Scanner; // Tilsvarer: import easyIO.*;
    
    class Metoder {
        public static void main(String[] args) {
            TestMetoder tm = new TestMetoder();
            tm.start();
        }
    }
    
    class TestMetoder {
        Scanner tast = new Scanner(System.in); // Tilsvarer: In tast = new In();
    
        void start() {
    	// Kaller en enkel metode:
    	metode1();
    
    	// Kaller en metode med én inn-parameter:
    	skrivTredoblet(123);
    
    	// Leser to tall fra tastatur, og overf?rer de til en metode
    	// som finner og skriver ut det h?yeste av de to tall:
    	skjerm.out("Skriv to tall (f.eks. 7 4): ");
    	int tall1 = tast.nextInt(); // Tilsvarer: ... = tast.inInt();
    	int tall2 = tast.nextInt(); // Tilsvarer: ... = tast.inInt();
    	finnH?yesteAv2(tall1, tall2);
    
    	// Kaller en metode som multipliserer de samme to tall lest
    	// inn ovenfor, og returnerer resultatet hit.
    	int resultat = multipliser( /* Fyll inn resten. . . */ );
    	skjerm.outln("Resultat multiplisert: " + resultat);
    
    	// Metode med array som inn-parameter:
    	double[] verdier = { 0, -3, 5, 10, -20, -7.7, 1.2, -0.01 };
    	//int antNeg = finnAntallNegativeTall(verdier);
    	//skjerm.outln("Arrayen verdier[] har " + antNeg + " negative tall.");
    	// <- Ta bort "//" i de to linjene over.
        }
    
        void metode1() {
    	skjerm.outln("Dette er metode1");
        }
    
        void skrivTredoblet(int x) {
    	int tredoblet = x * 3;
    	skjerm.outln("Tredoblet resultat = " + tredoblet);
        }
    
        void finnH?yesteAv2(int a, int b) {
    	// Hva mangler her?
    	// . . .
    
    	skjerm.outln("H?yest av de to tall er:" /* . . . */ );
        }
    
        int multipliser( /* Fyll inn resten. . . */) {
    	// . . .
    
    	return  0 ; // . . . Erstatt 0 med resultatet av x ganger y.
        }
    
        // Skriv metoden "finnAntallNegativeTall" her, som har en array med
        // double-verdier som inn-parameter, finner ut hvor mange av verdiene
        // i arrayen er negative tall, og returnerer det antallet (som en int).
    
        // . . .
    }
    
    import easyIO.*;
    
    class Metoder {
        public static void main(String[] args) {
            TestMetoder tm = new TestMetoder();
            tm.start();
        }
    }
    
    class TestMetoder {
        In tast = new In();
        Out skjerm = new Out();
    
        void start() {
    	// Kaller en enkel metode:
    	metode1();
    
    	// Kaller en metode med én inn-parameter:
    	skrivTredoblet(123);
    
    	// Leser to tall fra tastatur, og overf?rer de til en metode
    	// som finner og skriver ut det h?yeste av de to tall:
    	skjerm.out("Skriv to tall (f.eks. 7 4): ");
    	int tall1 = tast.inInt();
    	int tall2 = tast.inInt();
    	finnH?yesteAv2(tall1, tall2);
    
    	// Kaller en metode som multipliserer de samme to tall lest
    	// inn ovenfor, og returnerer resultatet hit.
    	int resultat = multipliser(tall1, tall2);
    	skjerm.outln("Resultat multiplisert: " + resultat);
    
    	// Metode med array som inn-parameter:
    	double[] verdier = { 0, -3, 5, 10, -20, -7.7, 1.2, -0.01 };
    	int antNeg = finnAntallNegativeTall(verdier);
    	skjerm.outln("Arrayen verdier[] har " + antNeg + " negative tall.");
        }
    
        void metode1() {
    	skjerm.outln("Dette er metode1");
        }
    
        void skrivTredoblet(int x) {
    	int tredoblet = x * 3;
    	skjerm.outln("Tredoblet resultat = " + tredoblet);
        }
    
        void finnH?yesteAv2(int a, int b) {
    	int h?yeste = a;
    	if (b > a) {
    	    h?yeste = b;
    	}
    	skjerm.outln("H?yest av de to tall er: " + h?yeste);
        }
    
        int multipliser(int a, int b) {
    	int produkt = a * b;
    	return produkt;
        }
    
        // Skriv metoden "finnAntallNegativeTall" her, som har en array med
        // double-verdier som inn-parameter, finner ut hvor mange av verdiene
        // i arrayen er negative tall, og returnerer det antallet (som en int).
        int finnAntallNegativeTall(double[] verdier) {
    	int antNegative = 0;
    	for (int i = 0; i < verdier.length; i++) {
    	    if (verdier[i] < 0) {
    		antNegative++;
    	    }
    	}
    	return antNegative;
        }
    }
    
    KJ?REEKSEMPEL:
    > java Metoder
    Dette er metode1
    Tredoblet resultat = 369
    Skriv to tall (f.eks. 7 4): 100 55
    H?yest av de to tall er: 100
    Resultat multiplisert: 5500
    Arrayen verdier[] har 4 negative tall.
    


  6. Finn feil:
    N?r vi pr?ver ? kompilere og kj?re dette programmet f?r vi feilmeldingene vist nedenfor. Hva er feil?
    1  class FinnFeil {
    2      int[] fat = new int[5];
    3      System.out.println("Feilplassert");
    4
    5      public static void main(String[] args) {
    6          FinnFeil ff = new FinnFeil();
    7          ff.metode();
    8      }
    9
    10      void metode() {
    11          for (int i = 0; i < 5; i++) {
    12              fat[i] = 10 * i;
    13          }
    14
    15          System.out.println(fat[5]);
    16          System.out.println(fat2);
    17          System.out.println(fat[1], 2);
    18      }
    19  }
    Hva betyr disse feilmeldingene, og hvordan retter vi feilene?
    (a)
      FinnFeil.java:3: <identifier> expected
          System.out.println("Feilplassert");
                            ^
      FinnFeil.java:3: illegal start of type
          System.out.println("Feilplassert");^
    
    (b)
      Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
              at FinnFeil.metode(FinnFeil.java:15)
              at FinnFeil.main(FinnFeil.java:7)
    
    (c)
      FinnFeil.java:16: cannot find symbol
      symbol  : variable fat2
      location: class FinnFeil
              System.out.println(fat2);
                                 ^
    (d)
      FinnFeil.java:17: cannot find symbol
      symbol  : method println(int,int)
      location: class java.io.PrintStream
              System.out.println(fat[1], 2);
                        ^
    
    L?sningsforslag kommer...


  7. Metode med inn og ut-parametre: kap. 7, oppg. 2 (side 133)
    Lag en metode som regner ut hypotenusen c i en rettvinklet trekant n?r vi g?r ut fra Pytagoras formel: c2 = a2 + b2 der a og b er lengden p? katetene ? de to andre sidene i trekanten.  Vi bruker a og b som parametre til metoden.  Du trenger da ? kalle kvadratrotmetoden i Math.sqrt(double_verdi) i den metoden du lager.  Returner verdien c som verdien p? metoden.  Test metoden ved ? kalle den i en dobbel for-l?kke for alle kombinasjoner av a og b med heltallsverdiene fra 1.0 til og med 6.0, og skriv ut svarene.
    double finnHypotenus(double a, double b) {
        // ...
        return c;
    }
    
    Hint: Kallet p? metoden kan se slik ut:  double c = finnHypotenus(a, b);  ...eller: System.out.println(finnHypotenus(a, b));
    class Hypotenus {
        public static void main(String[] args) {
    	HypotenusMetoder h = new HypotenusMetoder();
    	h.start();
        }
    }
    class HypotenusMetoder {
        void start() {
    	for (double a = 1; a <= 6; a++) {
    	    for (double b = 1; b <= 6; b++) {
    		double c = finnHypotenus(a, b);
    		System.out.printf("a=%.1f, b=%.1f  gir c=%.3f\n", a, b, c);
    	    }
    	}
        }
    
        double finnHypotenus(double a, double b) {
    	double c = Math.sqrt(a * a + b * b);
    	return c;
        }
    }
    
    KJ?REEKSEMPEL:
    a=1.0, b=1.0  gir c=1.414
    a=1.0, b=2.0  gir c=2.236
    a=1.0, b=3.0  gir c=3.162
    a=1.0, b=4.0  gir c=4.123
    a=1.0, b=5.0  gir c=5.099
    a=1.0, b=6.0  gir c=6.083
    a=2.0, b=1.0  gir c=2.236
    a=2.0, b=2.0  gir c=2.828
    a=2.0, b=3.0  gir c=3.606
    a=2.0, b=4.0  gir c=4.472
    a=2.0, b=5.0  gir c=5.385
    a=2.0, b=6.0  gir c=6.325
    a=3.0, b=1.0  gir c=3.162
    a=3.0, b=2.0  gir c=3.606
      ...osv...
    a=6.0, b=5.0  gir c=7.810
    a=6.0, b=6.0  gir c=8.485
    

Oppgaver til terminaltimen

  1. Filer, tekster, og metoder:
    (Samme som oppgave
    nr. 2, nr. 4, og nr. 5 for teoritimen.)


  2. Tallsiffer-oversetting:  kap. 6, oppg. 7 og 8 (side 116)
    (a) Lag et program som oversetter fra tallsiffer til tekst slik at f.eks. 3 blir oversatt til "tre".  Programmet skal kunne oversette alle 10 sifre (fra 0 til 9).  Hint: Bruk en array med tekstene "null", "en", "to", osv.
    (b) Lag et program som oversetter fra tekst til tall.  Programmet skal be brukeren skrive inn et tall mellom null og ni (med bokstaver), og skrive ut tilsvarende siffer. Hint: Bruk arrayen fra del (a).
    L?sningsforslag kommer...


  3. Finn feil:
    (Samme som oppgave nr. 6 for teoritimen.)


  4. Fortsett med Oblig 2:


  5. Pyramide med EasyIO: kap. 3, oppg. 1 (side 70)
    L?s oppgave 5 fra kapittel 1 (side 24) ved ? bruke formatert utskrift (Hint: Skriv ut alle linjene med samme bredde, og bruk Out.CENTER for ? sentrere utskriften av hver linje). 
    Hint II: Se ?verst p? side 52.

    Vi ?nsker ? skrive ut f?lgende tekst p? skjermen (med samme pyramideformatering):
         a
        a a
       a b a
      a c c a
     a d f d a
    
    Lag et Java-program som gj?r dette, ved ? bruke flere utskriftssetninger.
    import easyIO.*;
    
    class Pyramide {
        public static void main (String[] args) {
    	final int BREDDE = 10;
    	Out skjerm = new Out();
    
    	skjerm.outln("a", BREDDE, Out.CENTER);
    	skjerm.outln("a a", BREDDE, Out.CENTER);
    	skjerm.outln("a b a", BREDDE, Out.CENTER);
    	skjerm.outln("a c c a", BREDDE, Out.CENTER);
    	skjerm.outln("a d f d a", BREDDE, Out.CENTER);
        }
    }
    
    KJ?REEKSEMPEL:
    > java Pyramide
         a
        a a
       a b a
      a c c a
     a d f d a
    


  6. Ekstraoppgave: Pyramide uten EasyIO
    System.out.printf tilbyr mange flere m?ter ? formatere utskrift p? enn EasyIO, inkludert h?yre- og venstre-justering (f.eks. kodene "%7s" og "%-7s" skriver ut en String-verdi henholdsvis h?yre- og venstre-justert p? 7 plasser), men det er en formatering i EasyIO som printf ikke har direkte %-kode for: sentrering som vist i foreg?ende oppgave

    (a) Lag en metode som implementerer denne formateringen ved hjelp av printf (og uten EasyIO), metoden skal ta imot 2 parametre: teksten som skal skrives ut sentrert, og antall plasser man skal bruke.  Hint: Husk at tekst.length() gir deg lengden p? teksten.

    (b) Bruk metoden du lagde i (a) til ? l?se foreg?ende oppgave uten bruk av EasyIO.
    Send gjerne l?sningsforslaget ditt til josek [at] ifi.uio.no, s? legger jeg det ut her.


  7. Ukens n?tt: Sudoku hjelpeprogram
    (a) Lag et program som leser inn en Suduko-oppgave fra fil og lagrer de forh?ndsutfylte tallene i en 2-dimensjonal array.  Deretter g?r programmet i en l?kke som sp?r brukeren om et rad- og et kolonnenummer (i omr?det 1-9, eller 0 for ? avslutte).  Programmet skal s? svare brukeren med hvilke tall (1-9) som er mulige kandidater for plassering i den angitte rad/kolonne-plassen, ved ? finne ut hvilke av sifrene 1-9 ikke er allerede brukt i samme rad, kolonne, eller 3×3-omsluttende boks. 

    Input-filen er p? 9 linjer, med 9 tall per linje adskilt med mellomrom, og hvor 0 angir plassene som ikke har forh?ndsutfylt siffer i Sudoku-oppgaven.  Her er et eksempel p? en slik fil (med middels vanskelig oppgave).  Finn gjerne andre oppgaver fra aviser eller nettet. 
    6 0 7 0 0 0 0 8 0
    0 0 0 1 0 4 0 7 0
    0 0 5 0 0 8 0 3 0
    8 0 0 3 0 0 7 0 0
    4 0 0 5 0 6 0 0 8
    0 0 1 0 0 2 0 0 6
    0 8 0 4 0 0 5 0 0
    0 9 0 2 0 3 0 0 0
    0 7 0 0 0 0 1 0 3
    
    (b) Utvid deretter programmet slik at det g?r gjennom alle ikke-utfylte ruter (i stedet for ? be brukeren taste en), og for de rutene som bare har ett kandidatsiffer setter du sifferet inn i arrayen.  Gjenta prosessen med de gjenv?rende ikke-utfylte ruter helt til to p?f?lgende gjennomkj?ringer ikke finner nye tall ? sette inn.  Skriv ut resultatbrettet til slutt.
    Send gjerne l?sningsforslaget ditt til josek [at] ifi.uio.no, s? legger jeg det ut her.

Tibakemelding om dette oppgavesettet kan du skrive i bloggen eller sende p? mail til josek [a] ifi.uio.no