L?sningsforslag ukeoppg. 4:  14. - 20. sep (INF1000 - H?st 2011)

Metoder, flerdimensjonale arrayer  (kapittel 7.1-7.7, 5.7 i "Rett p? Java" 3. utg.)

NB! Legg merke til at disse er l?sningsforslag.  L?sningene dine trenger ikke ? v?re like med disse forslag for ? v?re riktige.  Det er vanlig i programmering at samme oppgave kan l?ses p? mange vidt forskjellige m?ter, og alle fremgangsm?ter er ok i INF1000 s? lenge de leder fram til riktig resultat og oppfyller kravene som st?r i oppgaveteksten.

M?l
?ve p? bruk av forgreninger, l?kker, arrayer, og metoder.

[N?kkeloppg.]: Oppgave merket med n?kkelsymbol er plukket ut som spesielt representativ for de viktigste temaene fra ukens forelesning, og alle b?r ha som minimumsm?l ? l?se denne selvstendig.

Oppgaver

  1. Enkel kalkulator med if-else og switch:
    [ NB! Vi bruker en litt spesiell m?te ? gi input i denne oppgaven, der bruker m? taste mellomrom mellom de tre delene av regnestykket (f.eks. "4 + 5"), men du vil l?re hvordan programmet kan godta andre skrivem?ter neste uke. ]
    (a) Lag en kalkulator som st?tter enkle regnestykker p? formen: tall operator tall, hvor de tre elementene er adskilt med mellomrom.  Tall er heltall, og operator er en av de fire regneartene: + - * /.  Eksempel p? kj?ring av programmet:
    Regnestykke: 4 + 5
    Resultat: 9
    
    Bruk tast.inInt() og tast.inChar(" ") for ? lese tall og regneart fra tastaturet (hvis du bruker EasyIO, hvis ikke se "Hint" nedenfor).  Mellomrommet i parentesene til inChar angir at den skal betrakte mellomrom som et skilletegn f?r og etter regnearten.  Dette er n?dvendig ? si fra til inChar, fordi den leser inn ett tegn av gangen.  Lagre tallene og operator i passende variabler, og bruk if-else-setninger til ? velge hvilken regneart skal utf?res. 
    Hint for ? l?se det uten EasyIO: Bruk scan.nextInt() i stedet for tast.inInt(), og scan.next().charAt(0) i stedet for tast.inChar(" ");.
    
    // L?sning p? (a) med EasyIO:
    import easyIO.*;
    
    class Kalkulator {
        public static void main(String[] args) {
            Out skjerm = new Out();
            In tast = new In();
    
    	skjerm.out("Regnestykke: ");
    	int a = tast.inInt();
    	char op = tast.inChar(" ");
    	int b = tast.inInt();
    
    	int svar = 0;
    	if (op == '+') {
    	    svar = a + b;
    
    	} else if (op == '-') {
    	    svar = a - b;
    
    	} else if (op == '*') {
    	    svar = a * b;
    
    	} else if (op == '/') {
    	    svar = a / b;
    	}
    
    	skjerm.outln("Resultat: " + svar);
        }
    }
    
    
    // L?sning p? (a) uten EasyIO:
    import java.util.Scanner;
    
    class Kalkulator {
        public static void main(String[] args) {
            Scanner tast = new Scanner(System.in);
    
    	System.out.print("Regnestykke: ");
    	int a = tast.nextInt();
    	char op = tast.next().charAt(0);
    	int b = tast.nextInt();
    
    	int svar = 0;
    	if (op == '+') {
    	    svar = a + b;
    
    	} else if (op == '-') {
    	    svar = a - b;
    
    	} else if (op == '*') {
    	    svar = a * b;
    
    	} else if (op == '/') {
    	    svar = a / b;
    	}
    
    	System.out.println("Resultat: " + svar);
        }
    }
    

    (b) Hvordan kan programmet endres for ? bruke en switch-setning i stedet for if-else?  (Hint: Se eksemplet p? side 80 i l?reboka, og husk ? ta med break;-setningene.)
    
    // L?sning p? (b) med EasyIO:
    import easyIO.*;
    
    class Kalkulator {
        public static void main(String[] args) {
            Out skjerm = new Out();
            In tast = new In();
    
    	skjerm.out("Regnestykke: ");
    	int a = tast.inInt();
    	char op = tast.inChar(" ");
    	int b = tast.inInt();
    
    	int svar = 0;
    	switch (op) {
    	  case '+':
     	           svar = a + b;
    	           break;
    	  case '-':
    	           svar = a - b;
    		   break;
    	  case '*':
    	           svar = a * b;
    		   break;
    	  case '/':
    	           svar = a / b;
    		   break;
    	}
    	skjerm.outln("Resultat: " + svar);
        }
    }
    
    
    // L?sning p? (b) uten EasyIO:
    import java.util.Scanner;
    
    class Kalkulator {
        public static void main(String[] args) {
            Scanner tast = new Scanner(System.in);
    
    	System.out.print("Regnestykke: ");
    	int a = tast.nextInt();
    	char op = tast.next().charAt(0);
    	int b = tast.nextInt();
    
    	int svar = 0;
    	switch (op) {
    	  case '+':
     	           svar = a + b;
    	           break;
    	  case '-':
    	           svar = a - b;
    		   break;
    	  case '*':
    	           svar = a * b;
    		   break;
    	  case '/':
    	           svar = a / b;
    		   break;
    	}
    	System.out.println("Resultat: " + svar);
        }
    }
    

    (c) Hva slags divisjon f?r vi utf?rt?, og hvordan kan vi endre programmet for ? f? utf?rt den andre typen divisjon uten ? endre deklarasjonen av de to innleste heltall?
    Programmet over gir heltallsdivisjon. For ? f? vanlig flyttallsdivisjon kan vi deklarere svar som double, og endre siste regnestykke til f.eks. ett av disse:
    	svar = (double) a / b;
    	svar = 1.0 * a / b;
    


  2. L?kker: Hva blir skrevet ut?
    Avgj?r uten ? bruke datamaskin hva som blir skrevet ut n?r f?lgende programsetninger utf?res.
    //(a)
           int a = 10;
           while (a < 20) {
               a += 4;
           }
           System.out.println("a = " + a);
    
    a = 22
    
    //(b)
           int sum = 0;
           for (int b = 1; b < 6; b += 2) {
               sum += b;
           }
           System.out.println("sum = " + sum);
    
    sum = 9
    //(c)
           int produkt = 1;
           for (int c = 1; c < 4; c++) {
               produkt = produkt * c;
    	   System.out.println(produkt);
           }
    
    
    1
    2
    6
     
    //(d)
           for (int d = 3; d >= 1; d--) {
               for (int e = 1; e <= 3; e++) {
                   System.out.println(d + e);
               }
           }
    
    4
    5
    6
    3
    4
    5
    2
    3
    4
    //(e)
           int teller = 0;
           for (int ytre = 0; ytre < 3; ytre++) {
               teller++;
               for (int indre = 0; indre < 3; indre++) {   
                   teller++;
               }
           }
           System.out.println(teller);
    
    12


  3. Utskrift og sum av oddetalls-array: kap. 5, oppg. 1-2 (side 99)
    (a) Skriv et program som inneholder en heltalls-array med f?lgende elementer: 1, 3, 5, 7, 9, 11, 13, 15, 17, 19.  Programmet skal inneholde en l?kke som skriver ut indeksen og verdien for alle elementene i arrayen.
    class Oddetall {
        public static void main(String[] args) {
    	int[] oddetall = { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };
    
    	for (int i = 0; i < oddetall.length; i++) {
    	    System.out.println("oddetall[" + i + "] = " + oddetall[i]);
    	}
        }
    }
    

    (b) Sum av elementene i en array: Vi bruker her samme array som i forrige oppgave: Beregn summen av elementene og skriv ut resultatet.
    	int sum = 0;
    	for (int i = 0; i < oddetall.length; i++) {
    	    sum = sum + oddetall[i];
    	}
    	System.out.println("sum = " + sum);
    


  4. S?ke etter tall i array:
    (a) Utvid programmet fra forrige oppgave slik at det ber bruker taste inn et tall, og deretter skriver ut en beskjed om det inntastede tallet finnes eller ikke finnes i arrayen.
    (b) Legg ogs? til en l?kke som skriver ut alle verdiene i arrayen som er mindre enn det inntastede tallet.
    import easyIO.*;
    
    class Uke3_Terminaloppg3 {
        public static void main(String[] args) {
            In tast = new In();
            int[] oddetall = { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };
    
            // (a) Finnes tallet?
            System.out.print("Tast inn et tall: ");
            int tall = tast.inInt();
    
            boolean funnet = false;
            for (int i = 0; i < oddetall.length; i++) {
                if (oddetall[i] == tall) {
                    funnet = true;
                }
            }
            System.out.print("Tallet " + tall);
            if (funnet) {
                System.out.println(" finnes i arrayen");
            } else {
                System.out.println(" finnes ikke i arrayen");
            }
    
            // (b) Skriv ut verdiene < tall:
            System.out.print("Verdier i arrayen som er < " + tall + ": ");
            for (int i = 0; i < oddetall.length; i++) {
                if (oddetall[i] < tall) {
                    System.out.print(oddetall[i] + " ");
                }
            }
            System.out.println();
        }
    }
    
    KJ?REEKSEMPEL:
    Tast inn et tall: 5
    Tallet 5 finnes i arrayen
    Verdier i arrayen som er < 5: 1 3 
    


  5. Flerdimensjonal array:
    To-dimensjonale arrayer brukes p? samme m?te som en-dimensjonale, men har to sett med klammer, og gjennomg?s best ved hjelp av to nestede for-l?kker, som vist i f?lgende program:
    import easyIO.*;
    class Array2D {
       public static void main(String[] args) {
    
            int[][] b = new int[3][4];
    
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 4; j++) {
    
                    b[i][j] = i * j;
    
                    System.out.println(<Hva mangler her?>);
                }
            }
       }
    }
    Arrayen kan illustreres slik:
      0 1 2 3
    0_
    1_
    2_
    KJ?REEKSEMPEL:
    > java Array2D     
    b[0][0] = 0
    b[0][1] = 0
    b[0][2] = 0
    b[0][3] = 0
    b[1][0] = 0
    b[1][1] = 1
    b[1][2] = 2
    b[1][3] = 3
    b[2][0] = 0
    b[2][1] = 2
    b[2][2] = 4
    b[2][3] = 6
    (a) Hvor mange elementer er det plass til i arrayen b vist over?
    (b) Hva er array-indeksene til array-elementene i tredje kolonne, og hvilke verdier f?r disse elementene i programmet over?
    (c) Fullf?r println-setningen i programmet ovenfor slik at det gir utskriften vist under "Kj?reeksempel".
    (a) 12 elementer (dvs. 3 x 4)
    (b) Tredje kolonne best?r av array-plassene b[0][2], b[1][2], og b[2][2], og
      verdiene i disse plassene er henholdsvis: 0, 2, og 4.
    (c) System.out.println("b[" + i + "][" + j + "] = "  + b[i][j]);
    
    Her kan du finne f?rste utkastet til denne oppgaven (som var lagt ut 14. sep sammen med beskjed ?verst p? denne siden om at oppgavesettet ikke var ferdig), og l?sningsforslag finner du der ogs?.


  6. Blokker og skop:
    Hvilke av disse programmene er lovlige?
    class Prog1 {
        public static void main(String[] args) {
            int k = 0;
            if (k >= 0) {
                int n = k + 1;
            }
            System.out.println(n);
        }
    }
    
    class Prog2 {
        public static void main(String[] args) {
            int k = 0;
            if (k >= 0) {
                int n = k + 1;
            }
            if (k < 0) {
                System.out.println(n);
            }
        }
    }
    
    class Prog3 {
        public static void main(String[] args) {
            int k = 0;
            if (k >= 0) {
                k++;
                System.out.println(k);
            }
        }
    }
    
    Prog1 og Prog2 er ulovlige, mens Prog3 er ok.
    


  7. inLine(), inChar(), og ordrel?kke:
    Lag et program som sp?r bruker etter et navn.  Programmet leser navnet inn ved hjelp av inLine() (hvis du bruker EasyIO) eller med nextLine (hvis du bruker Scanner); og "fyller" s? skjermen med navnet ved ? skrive det ut 100 ganger.  Videre skal programmet sp?rre bruker om hun vil gi et nytt navn (j/n).  Svaret leses n? med .inChar("\n\r") hvis du bruker EasyIO (for tips uten EasyIO se "Hint" nedenfor), og hvis det er 'j' gjentas hele prosessen; hvis svaret ikke er 'j' avsluttes programmet.  Kj?reeksempel:
    Skriv et navn: Ola Nordmann
    Ola Nordmann Ola Nordmann Ola Nordmann Ola Nordmann Ola Nordmann O
    la Nordmann Ola Nordmann Ola Nordmann Ola Nordmann Ola Nordmann Ol
    a Nordmann Ola Nordmann Ola Nordmann Ola Nordmann Ola  ...osv...
    Gi nytt navn? (j/n): j
    Skriv et navn:
    
    
    // L?sning med EasyIO:
    import easyIO.*;
    class Navn100 {
       public static void main(String[] args) {
           In tast = new In();
           Out skjerm = new Out();
    
           char svar = 'j'; // Startverdi
           while (svar != 'n') {
    
    	   skjerm.out("Skriv et navn: ");
    	   String navn = tast.inLine();
    
    	   for (int i = 0; i < 100; i++) {
    	       skjerm.out(navn + " ");
    	   }
    	   skjerm.outln();
    
    	   skjerm.out("Gi nytt navn? (j/n): ");
    	   svar = tast.inChar("\n\r");
           }
       }
    }
    
    
    // L?sning uten EasyIO:
    import java.util.*;
    class Navn100 {
       public static void main(String[] args) {
           Scanner scan = new Scanner(System.in);
    
           char svar = 'j'; // Startverdi
           while (svar != 'n') {
    
    	   System.out.print("Skriv et navn: ");
    	   String navn = scan.nextLine();
    
    	   for (int i = 0; i < 100; i++) {
    	       System.out.print(navn + " ");
    	   }
    	   System.out.println();
    
    	   System.out.print("Gi nytt navn? (j/n): ");
    	   svar = scan.nextLine().charAt(0);
           }
       }
    }
    
    Hint: Legg merke til det som st?r i parentesene til .inChar("\n\r") ovenfor (i varianten med EasyIO). Det som man skriver i disse parentesene kalles for "skilletegn" og angir hvilke tegn som ikke skal regnes som svaret (men i stedet regnes bare som skilletegn som adskiller evt. forskjellige svar). I dette tilfellet skal programmet hoppe over evt. linjeskift (\n) eller vognretur (\r) som bruker har tastet inn, og i stedet lese inn en vanlig bokstav fra tastatur, f.eks. 'j'. Det samme kan man ogs? f? til uten EasyIO, f.eks. ved hjelp av scan.nextLine().charAt(0); tips om dette finner du i kommentar #4 i bloggposten EasyIO.


  8. [N?kkeloppg.]: Metoder:
    (a) Endre strukturen til programmet ditt fra oppgave nr. 7 over slik at det f?lger den typen programstruktur som vi skal bruke i Oblig 2 (vist i skissen nedenfor), dvs. med en liten kontrollklasse ?verst, etterfulgt av en egen klasse for metodene.  Hele programmet med begge klassene lagres i én fil, kalt Navn100.java (dvs. navnet til klassen med metoden main()).  Lag bare én metode i hjelpeklassen, kalt ordrel?kke(), som gj?r alt som st?r i nr. 7 ovenfor.
    import easyIO.*;
    
    class Navn100 {
        public static void main(String[] args) {
            Hjelpeklasse hj = new Hjelpeklasse();
            hj.ordrel?kke(); // Kj?rer metoden ordrel?kke() i hjelpeklassen
        }
    }
    
    class Hjelpeklasse {
        // Klargj?ring for innlesing/utskrift, gjelder for hele klassen:
        In tast = new In();
        Out skjerm = new Out();
    
        String navn;
    
        void ordrel?kke() {
            char giNyttNavn = 'j'; // Startverdi
    
            while (giNyttNavn != 'n') {
                // - Be bruker taste et navn og les det inn med .inLine();
                // - Utskrift av navn 100 ganger.
                // - Sp?r om bruker vil "Gi nytt navn? (j/n):", og .inChar("\n\r"):
    
    
            }
        }
    }
    
    Mer info: Grunnen til at vi skriver programmet p? denne m?ten med to klasser vil bli klarere n?r vi kommer til kapittel 8, men har sammenheng med at vi ?nsker ? lage gode "objektorienterte" program der vi jobber med "objekter".  I denne skissen er det fem pekere til objekter: args[], hj, tast, skjerm, og navn.
    import easyIO.*;
    
    class Navn100 {
        public static void main(String[] args) {
            Hjelpeklasse hj = new Hjelpeklasse();
            hj.ordrel?kke(); // Kj?rer metoden ordrel?kke() i hjelpeklassen
        }
    }
    class Hjelpeklasse {
        // Klargj?ring for innlesing/utskrift, gjelder for hele klassen:
        In tast = new In();
        Out skjerm = new Out();
    
        String navn;
    
        void ordrel?kke() {
            char svar = 'j'; // Startverdi
    
            while (svar != 'n') {
                // - Be bruker taste et navn og les det inn med .inLine();
    	    skjerm.out("Skriv et navn: ");
    	    navn = tast.inLine();
    
                // - Utskrift av navn 100 ganger.
    	    for (int i = 0; i < 100; i++) {
    		skjerm.out(navn + " ");
    	    }
    	    skjerm.outln();
    
                // - Sp?r om bruker vil "Gi nytt navn? (j/n):", og .inChar("\n\r"):
    	    skjerm.out("Gi nytt navn? (j/n): ");
    	    svar = tast.inChar("\n\r");
            }
        }
    }
    

    (b) Flere metoder: Endre programmet slik at koden som skriver ut navnet 100 ganger flyttes til en egen metode kalt utskrift().  Husk ? legge inn et kall p? metoden p? det stedet i programmet du flyttet koden fra.
    import easyIO.*;
    class Navn100 {
        public static void main(String[] args) {
            Hjelpeklasse hj = new Hjelpeklasse();
            hj.ordrel?kke();
        }
    }
    class Hjelpeklasse {
        In tast = new In();
        Out skjerm = new Out();
    
        String navn;
    
        void ordrel?kke() {
            char svar = 'j';
            while (svar != 'n') {
    	    // Be bruker taste et navn og les det inn med .inLine():
    	    skjerm.out("Skriv et navn: ");
    	    navn = tast.inLine();
    
                // Kaller metoden utskrift():
    	    utskrift();
    
                // - Sp?r om bruker vil "Gi nytt navn? (j/n):"
    	    skjerm.out("Gi nytt navn? (j/n): ");
    	    svar = tast.inChar("\n\r");
            }
        }
        void utskrift() {
    	for (int i = 0; i < 100; i++) {
    	    skjerm.out(navn + " ");
    	}
    	skjerm.outln();
        }
    }
    

    (c) Inn-parameter: Endre programmet slik at det ogs? sp?r bruker hvor mange ganger navnet skal skrives ut.  Verdien som bruker taster skal overf?res som parameter til metoden utskrift() som du lagde i del (b).  Endre ogs? metoden utskrift(..) slik at den tar imot argumentet ved hjelp av parameteren int antall, slik:  void utskrift(int antall) {
    import easyIO.*;
    class Navn100 {
        public static void main(String[] args) {
            Hjelpeklasse hj = new Hjelpeklasse();
            hj.ordrel?kke();
        }
    }
    class Hjelpeklasse {
        In tast = new In();
        Out skjerm = new Out();
    
        void ordrel?kke() {
            char svar = 'j';
            while (svar != 'n') {
    	    // Be bruker taste et navn og les det inn med .inLine():
    	    skjerm.out("Skriv et navn: ");
    	    String navn = tast.inLine();
    
                // Kaller metoden utskrift():
    	    utskrift(navn);
    
                // - Sp?r om bruker vil "Gi nytt navn? (j/n):"
    	    skjerm.out("Gi nytt navn? (j/n): ");
    	    svar = tast.inChar("\n\r");
            }
        }
        void utskrift(String navn) {
    	for (int i = 0; i < 100; i++) {
    	    skjerm.out(navn + " ");
    	}
    	skjerm.outln();
        }
    }
    


  9. [N?tteoppg.]: Ukens n?tt 1: (vanskelig!)
    Lag et program som ber om 5 tall fra bruker, og deretter finner og skriver ut hvilke tall som er gjentatt blant disse.  F.eks. hvis bruker tastet inn 6 6 3 6 3, s? skal programmet gi meldingen: Tall som er gjentatt: 6 3 Send l?sningen din til josek [at] ifi.uio.no, s? legger jeg den ut i l?sningsforslagene!
    Send l?sningen din til josek [at] ifi.uio.no, s? legger jeg den ut i l?sningsforslagene!

    L?sningsforslag laget av Vegard Knutsen Lillevoll i gruppe 5 -- En veldig oversiktlig og godt kommentert l?sning, som lett kan utvides til flere enn 5 tall (bare ved ? bytte forekomstene av "5" til ?nsket antall).


  10. [N?tteoppg.]: Ukens n?tt 2: (vanskelig!)
    Lag en metode som skriver ut alle anagrammer av et ord p? 4 bokstaver som ligger i en char-array.  Anagrammene skal ha de samme 4 bokstavene, i alle mulige rekkef?lger og uten ? gjenta noen bokstav.  For eksempel, hvis ordet er deklarert som f?lger, er 4 av anagrammene som vist under, og totalt 24. Send l?sningen din til josek [at] ifi.uio.no, s? legger jeg den ut i l?sningsforslagene!
    char[] ord = { 'A', 'R', 'N', 'E' };
    
     Kj?reeksempel:
     ARNE
     AREN
     ANRE
     ANER
     ...20 ord til...
    
    Tips: En m?te ? l?se dette p? er med nestede l?kker som i utgangspunktet kan g? innom alle mulige kombinasjoner, inkludert AAAA, AAAE, osv. men slik at det bare blir utskrift av de med 4 forskjellige bokstaver.  Bruk den tomme strengen "" og + i utskriftssetningen for ? konvertere char-ene til tekst: System.out.println("" + ord[3] + ord[2] ···


  11. Tips til Emacs: (for spesielt interesserte)
    • Emacs-forkortelser: Legg til f?lgende fem linjer i din ~/.emacs-fil:
      (define-abbrev-table 'java-mode-abbrev-table '(
          ("psv" "public static void main(String[] args) {" nil 0)
          ("sop" "System.out.println" nil 0)
      ))
      (abbrev-mode 1)
      Deretter starter du Emacs p? nytt. N?r du skriver psv i et Java-program (etterfulgt av mellomrom eller linjeskift) s? vil det n? bli utvidet til: public static void main(String[] args) {, og tilsvarende for sop etterfulgt av (.  Legg gjerne til flere forkortelser.  Mer info om filen ~/.emacs kan du finne i Ukeoppgaver 2.
    • Undo: For ? angre siste redigering trykk C-_ (dvs. Ctrl-understrek), eller klikk p? ikonet med bilde av en ?b?yd pil? ?verst i Emacs-vinduet.
    • Copy/paste: For ? kopiere tekst fra et hvilket som helst sted p? skjermen til Emacs, start med ? markere teksten ved hjelp av musa. Deretter flytter du mus-pekeren til det stedet i Emacs-vinduet der du vil lime inn teksten, og trykker musens midt-knapp (dvs. hjul-tasten) rett ned. Ferdig! Du trenger alts? ikke trykke Ctrl-c eller h?yreklikk > Copy for ? velge teksten i Emacs, det er nok ? markere det.
    • Cut/paste: Hvis du vil klippe bort tekst og flytte det til et annet sted i Emacs-vinduet: markér teksten; trykk Delete-tasten eller C-w for ? klippe det bort; flytt tekst-mark?ren til ?nsket sted; og trykk Insert-tasten eller C-y for ? lime inn.
    • Splittet vindu: For ? kunne se to filer samtidig kan du dele Emacs-vinduet i to ved ? trykke C-x 2 ("C-" st?r for Ctrl-tasten). For ? g? tilbake til ? vise én fil klikk med musa p? ?nsket del av splitt-vinduet og trykk C-x 1.
    • Flere vinduer: For ? ?pne et ekstra-Emacs-vindu slik at du kan se to filer samtidig enda lettere trykk C-x 52. Husk C-x C-f for ? ?pne en fil i det nye vinduet.
    • Innrykk: Du kan la Emacs sette riktig innrykk i hele programmet ved ? trykke C-x h og deretter velge i menyene ?verst: Java > Indent Line or Region.
    • Flere tips til Emacs kan du finne i Emacs-oppgavene fra Forkurs i informatikk


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