L?sningsforslag ukeoppg. 4: 20. - 24. sep (INF1000 - H?st 2010)
Teori for Oblig 2: Mer om l?kker og arrayer (kap. 4 - 5); og metoder (kap. 7.1 - 7.9)
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
F? ?velse i teorien som trengs for ? l?se
Oblig 2.
Hovedtema i obligen er l?kker, arrayer, og metoder uten parametre,
og f?lgende oppgaver gir nyttig trening i dette slik at du blir
bedre i stand til ? l?se obligen.
Oppgaver til teoritimen
- Enkle l?kker med tall:
(a) Nedtelling: Lag et program med en l?kke som teller ned fra 10 til 0. Bruk en teller-variabel med startverdi 10 og redusér den med 1 i hver gjennomgang av l?kka. Utskriften skal bli:...10 ...9 ...8 ...7 ...6 ...5 ...4 ...3 ...2 ...1 ...0
class Bombe { public static void main(String[] args) { for (int teller = 10; teller >= 0; teller--) { System.out.print(" ..." + teller); } System.out.println(); } }
Java-nedtelling: (kun for spesielt interesserte) Hvis du vil legge inn 1-sekunds pause f?r hvert tall skrives ut kan du skrive "Thread.sleep(1000); // Vent 1000 millisek." inne i for-l?kka og endre "(String[] args)" til "(String[] args) throws Exception". Exceptions er ikke pensum men omtales i kap. 18. Bare kap. 1 - 9 (og litt av 12) er pensum.
(b) Dobling: Lag en l?kke som starter med ? skrive ut tallet 2, og deretter dobler tallet, skriver det ut, og gjentar prosessen helt til 10 tall er skrevet ut. Bruk en teller-variabel "i" som teller de 10 gangene, og en annen variabel for tallet som ganges med 2 i hver omgang av l?kka og skrives ut. Utskriften skal bli:2 4 8 16 32 64 128 256 512 1024
class PowersOf2 { public static void main(String[] args) { int potens2 = 1; for (int i = 0; i < 10; i++) { potens2 = potens2 * 2; System.out.print(potens2 + " "); } System.out.println(); } }
(c) Tabell: Lag to nestede for-l?kker som gir f?lgende utskrift. Det skal bare skrives ut ett tall av gangen, som skal v?re verdien til telleren i den ytre l?kka (som g?r fra 1 til 3 og skal hete rad) ganget med telleren i den indre l?kka.1 2 3 4 2 4 6 8 3 6 9 12
class DobbelLoop { public static void main(String[] args) { int produkt = 1; for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 4; j++) { produkt = i * j; System.out.print(produkt + " "); } System.out.println(); } } }
- 2D-array (to-dimensjonal array) med tall:
(a) Utskrift: Lag to nestede for-l?kker som setter inn f?lgende verdier i en 2D-array og skriver de ut. Arrayen skal deklareres slik:int[][] tabell = new int[3][4];. Se oppgave nr. 1 (c) over for tips om disse verdiene. Husk at indeksene i arrayen starter fra 0, ikke 1. Verdien i tabell[2][3] skal v?re 12.1 2 3 4 2 4 6 8 3 6 9 12
class Array2D { public static void main(String[] args) { int[][] tabell = new int[3][4]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { tabell[i][j] = (i + 1) * (j + 1); System.out.print(tabell[i][j] + " "); } System.out.println(); } } }
(b) Sum av kolonne: Skriv programkode som beregner summen av verdiene i hver kolonne i ovennevnte array og skriver summene ut. Dette ligner p? en deloppgave i oblig 2!6 12 18 24
System.out.println("Sum av kolonner:"); for (int kol = 0; kol < 4; kol++) { int sumkol = 0; for (int rad = 0; rad < 3; rad++) { sumkol += tabell[rad][kol]; } System.out.print(sumkol + " "); } System.out.println();
(c) S?k etter tall: Utvid programmet slik at det ber bruker taste inn et tall og deretter ser om tallet finnes i arrayen. Hvis tallet finnes skal alle array-indeksene der det ligger skrives ut, hvis ikke skal det gis beskjed om at tallet ikke finnes.Hvilket tall s?ker du: 8 Tallet finnes i tabell[1][3]
class Array2D { public static void main(String[] args) { int[][] tabell = new int[3][4]; // (a) for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { tabell[i][j] = (i + 1) * (j + 1); System.out.print(tabell[i][j] + " "); } System.out.println(); } // (b) System.out.println("\n (b) Sum av kolonner:"); for (int kol = 0; kol < 4; kol++) { int sumkol = 0; for (int rad = 0; rad < 3; rad++) { sumkol += tabell[rad][kol]; } System.out.print(sumkol + " "); } System.out.println(); // (c) System.out.print("\n(c) Hvilket tall s?ker du: "); int tall = new easyIO.In().inInt(); for (int rad = 0; rad < 3; rad++) { for (int kol = 0; kol < 4; kol++) { if (tall == tabell[rad][kol]) { System.out.println("Tallet finnes i tabell[" + rad + "][" + kol + "]"); } } } } } KJ?REEKSEMPEL: > java Array2D 1 2 3 4 2 4 6 8 3 6 9 12 (b) Sum av kolonner: 6 12 18 24 (c) Hvilket tall s?ker du: 4 Tallet finnes i tabell[0][3] Tallet finnes i tabell[1][1]
- 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.
- inLine(), inChar(), og ordrel?kke:
Lag et program som sp?r bruker etter et navn. Programmet leser navnet inn vha. inLine();, 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"), og hvis det er 'j' gjentas hele prosessen; hvis svaret er 'n' 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:
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"); } } }
Tips til Oblig 2: Legg merke til det som st?r i parentesene til .inChar("\n\r") ovenfor. Dette angir at inChar skal 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 b?r du gj?re i deloppgave 1 (c) i oblig 2. - Metoder:
(a) Endre strukturen til programmet ditt fra oppgave nr. 4 over slik at det f?lger malen fra 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. 4 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 vha. 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(); } }
Oppgaver til terminaltimen
- L?kker: Gangetabell
(a) Lag et program som ber bruker taste inn et tall, og skriver ut gangetabellen for det tallet, ganget med 1, 2, osv. til 12. Hvis bruker taster inn 5 skal resultatet se slik ut:5 x 1 = 5 5 x 2 = 10 5 x 3 = 15 5 x 4 = 20 5 x 5 = 25 5 x 6 = 30 ...osv...
L?sningsforslag kommer...
(b) Endre programmet slik at utskriften av gangetabellen lages i en egen metode. Sett opp programmet med to klasser som vist i nr. 5 ovenfor.L?sningsforslag kommer...
- L?kker: Fibonacci-tallene
Lag et program som skriver ut de 15 f?rste tall i Fibonaccif?lgen. F?lgen er definert ved at de to f?rste tall er 0 og 1, og hvert neste tall er summen av de to foreg?ende. Utskriften skal bli:0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
class Fibonacci { public static void main(String[] args) { int nestSiste = 0; int siste = 1; // Skriver ut de to f?rste tall: System.out.print(nestSiste + " "); System.out.print(siste + " "); // Skriver ut 3. til 15. tall i f?lgen: for (int i = 3; i <= 15; i++) { int tmp = siste; // Midlertidig variabel siste = siste + nestSiste; nestSiste = tmp; System.out.print(siste + " "); } System.out.println(); } }
- Arrayer, inLine(), inChar(), og enkle metoder:
(Samme oppgaver som i nr. 2, 4, og 5 for teoritimen.)
- Fortsett med Oblig 2:
Tips: Begynn med ? l?se foreg?ende oppgave (?Arrayer, inLine(), ...?). Der vil du finne problemstillinger som ligner mye p? det som skal gj?res i Oblig 2, men litt enklere slik at obligen blir lettere ? gj?re etter at du har l?st disse oppgavene.
- Ekstraoppgave:
(a) Endre strukturen i Fibonacci-programmet du lagde ovenfor slik at det f?lger malen fra oblig 2 (vist ogs? ovenfor i oppgave nr. 5 for teoritimen), med en kontrollklasse ?verst, etterfulgt av en hjelpeklasse for metodene. Bruk tre metoder i hjelpeklassen: en ordrel?kke som skriver ut f?lgende meny, og en metode for hvert av de 2 menyvalgene:
1. Skriv ut de 15 f?rste tall i Fibonaccif?lgen 2. Test om et tall h?rer til f?lgen
Metoden for ordre 2 ber bruker taste inn et tall, og g?r s? i en l?kke som genererer Fibonacci-tallene frem til det bruker-inntastede tallet. Deretter gis det melding til bruker om tallet h?rte til f?lgen eller ikke.Mer info: Fibonacci-tallene forekommer mye i naturen, bl.a. i tregrener, blomster, kongler og kaniner.import easyIO.*; class Fibonacci { public static void main(String[] args) { FibonacciMetoder fib = new FibonacciMetoder(); fib.ordrel?kke(); } } class FibonacciMetoder { In tast = new In(); Out skjerm = new Out(); void ordrel?kke() { int ordre = 0; while (ordre != 3) { // Meny: skjerm.outln("1. Skriv ut de 15 f?rste tall i Fibonaccif?lgen"); skjerm.outln("2. Test om et tall h?rer til f?lgen"); // Leser kommando fra bruker: skjerm.out("Velg kommando (3=Avslutt): "); ordre = tast.inInt(); switch (ordre) { case 1: skriv15Fib(); break; case 2: testFibTall(); break; default: break; } System.out.println(); } } void skriv15Fib() { int nestSiste = 0; int siste = 1; System.out.print(nestSiste + " "); System.out.print(siste + " "); for (int i = 3; i <= 15; i++) { int tmp = siste; // Midlertidig variabel siste = siste + nestSiste; nestSiste = tmp; System.out.print(siste + " "); } System.out.println(); } void testFibTall() { skjerm.outln(); skjerm.out("Skriv et tall for ? teste om det er Fibonacci-tall: "); int inntastet = tast.inInt(); int nestSiste = 0; int siste = 1; int i = 2; // i: Plass i Fib.f?lgen til n?v?rende "siste" // S? lenge "siste" er < enn inntastet generér neste Fib.-tall: for ( ; siste < inntastet; i++) { int tmp = siste; siste = siste + nestSiste; nestSiste = tmp; } if (siste == inntastet) { System.out.println(inntastet + " er Fibonacci-tall nr. " + i); } else if (inntastet == 0) { System.out.println(inntastet + " er Fibonacci-tall nr. 1"); } else { System.out.println(inntastet + " er IKKE et Fibonacci-tall."); } } } KJ?REEKSEMPEL: > java Fibonacci 1. Skriv ut de 15 f?rste tall i Fibonaccif?lgen 2. Test om et tall h?rer til f?lgen Velg kommando (3=Avslutt): 1 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 1. Skriv ut de 15 f?rste tall i Fibonaccif?lgen 2. Test om et tall h?rer til f?lgen Velg kommando (3=Avslutt): 2 Skriv et tall for ? teste om det er Fibonacci-tall: 233 233 er Fibonacci-tall nr. 14 1. Skriv ut de 15 f?rste tall i Fibonaccif?lgen 2. Test om et tall h?rer til f?lgen Velg kommando (3=Avslutt): 2 Skriv et tall for ? teste om det er Fibonacci-tall: 234 234 er IKKE et Fibonacci-tall.
(b) (middels vanskelig) Utvid ordre 2 slik at den ogs? sier hvilket Fibonacci-tall er n?rmest det bruker-inntastede tallet.Send gjerne l?sningsforslaget ditt til josek [at] ifi.uio.no, s? legger jeg det ut her. - Ukens n?tt: (veldig 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.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] ··· Send gjerne l?sningsforslaget ditt til josek [at] ifi.uio.no, s? legger jeg det ut her.
L?sningsforslag laget av Viktor F. Andersen i gruppe 16:
class VeldigVanskeligNott { public static void main (String args[]) { char[] ord = {'A', 'R', 'N', 'E'}; int antall = 1; // for ? nummerere og telle ordene String kolon = ": "; // for avansert estetikk // f?lgende g?r gjennom hvert tegn i arrayen, og s?rger for at // ingen like tegn blir skrevet ut likt for (int i = 0; ord.length > i; i++) { for (int j = 0; ord.length > j; j++) { for (int k = 0; ord.length > k; k++) { for (int l = 0; ord.length > l; l++) { if (ord[l] != ord[i] && ord[l] != ord[j] && ord[l] != ord[k] && ord[k] != ord[j] && ord[k] != ord[i] && ord[j] != ord[i]) { System.out.println(antall + kolon + ord[i] + ord[j] + ord[k] + ord[l]); antall++; if (antall >= 10) { // dette gj?r at kolonnen kolon = ": "; // med tall g?r rett } } } } } } } }
Tibakemelding om dette oppgavesettet kan du skrive i bloggen eller sende p? mail til josek [a] ifi.uio.no