Tentamen i EDA11 Programmeringsteknik för F, E, I, π och N Måndagen den 6 mars 26 Skrivtid: 8. 13. Tillåtna hjälpmedel: Java-snabbreferens, hammare, spik och tråd. Resultat: Resultatet av denna tentamen rapporteras direkt in i LADOK vi kommer inte att sätta upp någon tentamenslista, så ditt resultat kommer inte att anslås för andra än dig själv. Behörighet: För att vara behörig att skriva tentamen måste du ha blivit godkänd på samtliga inlämningsuppgifter. Den som skriver utan att ha blivit godkänd på uppgifterna, och inte fått dispens, kommer att få sin tentamen annullerad du behöver dock inte vara orolig om du har blivit godkänd på dina uppgifter, men de av något skäl inte har förts in i pthandin kontakta i så fall Christian. Instruktioner: Tentornas svårighetsgrad kan variera, men det är alltid lika lätt/svårt att bli godkänd en svårare tenta bedöms snällare än en lätt tenta, och vice versa. Oavsett hur lätt/svår du tycker att denna tenta är, gör ditt bästa. För att bli godkänd behöver du inte göra något som du inte redan gjort på inlämningsuppgifterna. Denna tentamen består av två delar: Del 1 består av uppgift 1-4, som alla bör behandla. Del 2 utgörs av uppgift 5, och riktar sig till dem som strävar efter överbetyg. Uppgiften är inte nödvändigtvis svårare än uppgifterna i del 1, men den kommer att rättas något strängare. Det maximala poängantalet på varje uppgift är angivet vid uppgiften, betygsgränser bestäms i samband med rättningen. Om det är något du är osäker på under tentamen, fråga Christian. Du får gärna skriva på papprets båda sidor. Direkt efter tentamen kommer ett lösningsförslag att läggas ut på kurshemsidan. Del 1 Denna del av tentamen bör alla behandla efter bästa förmåga, godkänt kan ge betyget 3 eller 4. Du bör vara noggrann med variabelnamn och indragningar om du glömmer en klammer, och inte indragningarna visar tydligt hur du har tänkt, så kommer vi att göra poängavdrag. Som en del av er kanske noterat gick vinter-os nyligen av stapeln, och i samband med det publicerades ofta så kallade medaljlistor. Efter spelen såg medaljfördelningen ut så här: 1
Guld Silver Brons 1. Tyskland 11 12 6 2. USA 9 9 7 3. Österrike 9 7 7 4. Ryssland 8 6 8 5. Kanada 7 1 7 6. Sverige 7 2 5 13. Norge 2 8 9 17. Australien 1 1 19. Finland 6 3 Som framgår av tabellen placerade sig Finland efter en stor vintersportnation som Australien, men före både Kenya och Senegal. Vi skall i denna del av tentamen skriva ett program för att göra medaljsammanställningar, och skall då använda följande klasser: class Country: Country(String code, String name) Skapar ett nytt land. code: landets landskod (exempelvis SWE), name: landets namn (exempelvis Sverige). String getname() Ger landets namn. String getcode() Ger landets landskod (exempelvis SWE). void addplace(int place) Noterar att landet fått en given placering i en gren. place: placering (vi är bara intresserade av placeringarna 1... 6). int getnbroftimes(int place) Ger antalet gånger landet kommit på en given plats. place: placering som efterfrågas (1... 6, annars returneras värdet ). int compareto(country other) Jämför landet med ett annat land, returnerar ett negativt heltal om landet skall placeras före det andra landet i medaljtabellen, ett positivt tal om det skall placeras efter det andra landet, och om de båda länderna har samma medaljfördelning. other: det land vi skall jämföra med. class OlympicGames: OlympicGames (int maxnbrofcountries) Skapar ett nytt olympiskt spel. maxnbrofcountries: maximalt antal deltagande länder. void inputresults() Läser in resultat i en gren se nedan för mer information. void printmedalstatistics() Skriver ut en medaljsammanställning se nedan för mer information. I klassen Country håller vi reda på hur många gånger landet fått placeringarna 1..6 i attributet countplace, som är en heltalsvektor antalet förstaplaceringar (guld) skall lagras i index, antalet andraplaceringar i index 1, och så vidare, till antalet 6:e-placeringar, som lagras i index 5. När vi jämför två länder med varandra, med compareto, så jämförs i första hand antalet förstaplatser, om de är lika jämförs antalet andraplatser, osv, ner till antalet 6:e-platser. Inmatningen av resultat i inputresults går till på följande sätt (kursiverad text är det som användaren matar in): Vilket land är SWE? Sverige 2 FRA Vilket land är FRA? Frankrike 3 SWE 2 4 ITA Vilket land är ITA? Italien 5 ITA 6 ITA
Användaren matar in placering och landskod för ett antal länder, inmatningen avslutas med att användaren skriver in placeringen. När vi stöter på en landskod som tidigare inte påträffats skall programmet fråga vad landet heter (ingen fråga skall ställas när vi får en landskod som vi haft tidigare). Ibland delas placeringar, exempelvis placerade sig Kanada, Schweiz, Slovakien och USA på delad 5:e-plats i herrarnas ishockeyturnering. Alla de fyra länderna får i detta fall placeringen 5 (som anges i indata). Det är användarens skyldighet att se till att placeringarna blir rätt inmatade ditt program kan alltså förutsätta att den placering du läser in är korrekt. Du behöver inte bekymra dig om formatet vid inläsningen, du kan läsa placeringen med Keyboard.nextInt() och därefter landskoden med Keyboard.nextLine() du behöver inte ta hänsyn till mellanrummet mellan placering och landskod, och du behöver inte heller ta hänsyn till radbrytningar. Vid utskrift av medaljlistan skall länderna sorteras, men klassen Country implementerar gränssnittet Comparable<Country> (du behöver inte göra något annat än att skriva operationen compareto som finns i klasspecifikationen ovan), så i klassen OlympicGames kan vi sortera en vektor med länder genom att anropa standardoperationen Arrays.sort på följande sätt: Arrays.sort(vektornamn, index för första värde, 1 + index för sista värde); Om du istället väljer att lägga länderna i en lista kan du använda Collections.sort. Formatet på utskriften framgår av programexamplet nedan du behöver inte skriva ut antalet medaljer i så prydliga kolumner som i exemplet. Uppgift 1 (3 poäng) Rita en figur som visar ett OlympicGames-objekt och länderna Sverige, Norge och Finland med de medaljer de fick i Turin (se ovan) du får själv hitta på antalet placeringar 4... 6 för respektive land. Uppgift 2 (8 poäng) Implementera klassen Country. Klassen skall ha attributet countplace som beskrivs i texten ovan, övriga attribut får du själv bestämma. Observera att operationen compareto ingår i klassen (den står lite olyckligt i specifikationen ovan). Uppgift 3 (1 poäng) Implementera klassen OlympicGames. Du får själv bestämma vilka attribut du skall ha (du behöver hålla reda på alla deltagande länder). Vi vill ha ett huvudprogram som låter användaren mata in placeringar och skriva ut medaljstatistik. Eftersom idrott och pengar numera hör ihop, får de deltagande länderna pengar från internationella olympiska kommittén för de olika placeringar deras länder tagit. Vi vill därför ha följande två operationer: I klassen Country: double pricemoney(double[] amounts), som beräknar ett lands totala prissumma, givet en vektor amounts med de belopp olika placeringar ger (sex reella tal, värdet i index är det belopp ett guld ger, värdet i index 5 är det belopp en sjätteplats ger). I klassen OlympicGames: void printpricemoney(), som läser in det belopp man får för varje placering (1-6), och skriver ut prissumman för samtliga länder (sorterade i medaljordning). Exempel på användning av programmet: Vad vill du göra (-3)? 1 Vilket land är SWE? Sverige 3
2 FRA Vilket land är FRA? Frankrike 3 SWE 4 ITA... som ovan... Vad vill du göra (-3)? 1 2 FIN Vilket land är FIN? Finland... fler resultat... Vad vill du göra (-3)? 2 Sverige 2 1 Frankrike 1 Finland 1 Tjeckien 1 Italien Vad vill du göra (-3)? 3 Ange prispengarnas storlek: Pengar för plats 1: 5 Pengar för plats 2: 25 Pengar för plats 3: 125 Pengar för plats 4: 6 Pengar för plats 5: 3 Pengar för plats 6: 15 Sverige 1125 Frankrike 25 Finland 25 Tjeckien 125 Italien 15 Vad vill du göra (-3)? Välkommen tillbaka om 4 år Uppgift 4 (9 poäng) Implementera operationen pricemoney i klassen Country, och printpricemoney i klassen OlympicGames (du får själv välja om du vill skriva dem för sig, eller inne i klasserna i uppgift 2 och 3). Skriv även ett huvudprogram enligt beskrivningen ovan. Du behöver inte skriva ut tal i jämna kolumner! Del 2 Följande del av tentamen behöver bara behandlas av dem som eftersträvar betyget 5 den rättas inte om inte första delen av tentamen är godkänd. Resultatet på denna del räknas bara in i totalresultatet om den är godkänd, dvs ger minst 4 poäng (man kan alltså inte höja sitt betyg genom att ta någon enstaka poäng på denna del). Uppgiften är inte nödvändigtvis svårare än uppgifterna i föregående del, men vid rättningen av denna del har vi större krav på stil och effektivitet än då vi rättar del 1. Vi skall lösa ett geometriskt problem, närmare bestämt problemet att bestämma den kortaste väg som omsluter ett antal givna punkter i x yplanet. Figuren visar ett exempel: På engelska kallas detta för the convex hull. 4
I exemplet har vi nio punkter, och den kortaste väg som omsluter samtliga punkter består av fem linjesegment (varje linjesegment går mellan två punkter). Det finns flera sätt att hitta den sökta vägen, vi skall använda en metod som kallas the gift wrapping algorithm: 1. Vi börjar med att slå spikar i varje punkt, låt spikarna sticka upp en bit. 2. Välj ut den punkt som har lägst y- koordinat (alltså den som ligger längst ner), och fäst en lång tråd i spiken i denna punkt. 3. Dra ut tråden rakt åt höger, utmed bordsytan, och dra änden på tråden moturs, precis ovanför bordsytan, ett helt varv runt alla spikar (håll tråden utsträckt hela tiden). 4. Den kortaste vägen runt samtliga punkter går genom alla de spikar som tråden stött i. Vi skall alltså börja med att leta upp den punkt som har lägst y-koordinat kalla denna för startpunkten. Därefter skall vi leta upp den punkt som har minst vinkel sett från startpunkten, hoppa till denna punkt, och fortsätta på samma sätt därifrån, ända tills vi kommer tillbaka till startpunkten (observera att vinkeln till nästa punkt hela tiden blir större och större). För att bestämma vinkeln mellan två punkter kan du använda arctan-funktionen, om du är osäker på detaljerna, skriv en kommentar i programkoden (det är inte hela världen om det blir lite fel). Du kan använda double angle = CSMath.arctan(dy,dx); för att beräkna arctan(dy/dx) du får då värden i intervallet... 2π (den fungerar även då dx = ). Vi förutsätter följande: Det finns minst tre punkter. Det finns inte två punkter som har samma koordinater. Det finns en punkt som har mindre y- koordinat än alla de andra (dvs som ligger nedanför alla andra punkter). Vi vill ha ett program med klasserna Point, som beskriver en punkt i x y- planet, LineSegment, som beskriver ett linjesegment mellan två punkter, Path, som beskriver en följd av linjesegment, och PointSet, som beskriver en mängd punkter. Du får själv bestämma vilka attribut och operationer du vill ha i de olika klasserna, operationen som bestämmer kortaste vägen (som är ett Pathobjekt) bör ligga i klassen PointSet. Vi vill dessutom ha ett huvudprogram som läser in koordinaterna för ett antal punkter, och skriver ut längden av den kortaste vägen runt samtliga punkter indata avslutas med en negativ x-koordinat: Ange punkter: 7 2 5 3 2 1 3 4 6 5 8 5 1 7 4 7 6 8-1 Kortaste vägen är 23.486 Programmet skall lagra den kortaste vägen i ett Path-objekt (som du dock inte behöver skriva ut). Uppgift 5 (1 poäng) Implementera klasserna Point, LineSegment, Path och PointSet, och skriv ett program som läser in ett antal punkter och skriver ut längden av den kortaste vägen runt punkterna. 5