Tentamen Programmeringsteknik II 2016-10-19 Skrivtid: 0800 1300 Tänk på följande Lägg uppgifterna i ordning. Skriv uppgiftsnummer och din kod överst i högra hörnet på alla papper. Fyll i försättssidan fullständigt. Såvida inget annat anges får man bygga på lösningar till föregående uppgifter även om dessa inte har lösts. Det är tillåtet att införa hjälpmetoder och hjälpklasser. Uttrycket skriv en metod som skall alltså inte tolkas så att lösningen inte får struktureras med hjälp av flera metoder. Alla uppgifter gäller programmeringsspråket Java och programkod skall skrivas i Java. Koden skall vara läslig dvs den skall vara vettigt strukturerad och indenterad. Namn på variabler, metoder, klasser etc skall vara beskrivande men kan ändå hållas ganska korta. Observera att betyget påverkas negativt bland annat av icke-privata eller onödiga instansvariabler, dålig läslighet, upprepning av identisk kod, underlåtenhet att utnyttja given eller egen tidigare skriven metod, underlåtenhet att utnyttja arv och lösningar som har väsentligt sämre komplexitet än nödvändigt t ex Θ(n 2 ) i stället för Θ(n log n). Observera Skrivningen består av två delar. Lösningarna till uppgifterna på del A ska skrivas direkt på skrivningsformuläret och lämnas in. Rutorna är tilltagna i storlek så att de ska rymma svaren. Om du ändå inte får plats får du skriva på baksidan. Svaren på del B skrivs på vanligt papper med nytt papper för varje uppgift. Bedömning och betygsättning För att bli godkänd (betyg 3) krävs att minst cirka 75% av uppgifterna på A-delen är i stort sett rätt lösta. För betyget 4 krävs dessutom att minst hälften av uppgifterna på B-delen och betyg 5 att alla uppgifterna på B-delen är i stort sett rätt lösta. Vid bedömning för dessa betyg tas även hänsyn till kvalitén på lösningarna på A-delen. Observera att B-delen inte rättas om inte A-delen är godkänd. Lycka till!
Inledning I bilagorna finns ett antal mer eller mindre ofullständiga klasser. Klassen BasicList innehåller några grundläggande komponenter för att skapa och hantera enkellänkade listor av heltal. Varje tal kan förekomma flera gånger. Exempel på ett listobjekt: (5, 2, 7, 17, 2, 18, 18, -7) Klassen Queue ärver från BasicList och adderar möjligheten att lägga till element sist i listan med O(1) operationer. Klassen PriorityQueue ärver också från BasicList och lägger till en metod för att ta ut det minsta värdet ur listan. BasicList Queue PriorityQueue first 3 1 4 3 List och PriorityQueue objekt first last 3 1 4 3 Queue objekt innehåller en main-metod som exemplifierar användningen av list- Klassen ListTest klasserna. Klassen BST innehåller en variant av binära sökträd med tal som nycklar. Till skillnad från i vanliga binära sökträd kan samma nyckel förekomma flera gånger. Klassen Parser definierar (delar av) en numerisk kalkylator.
Anmälningskod: Del A (obligatorisk för alla) A1. Ringa in rätt svarsalternativ! a) Att göra inlägg av n slumptal i ett från början tomt binärt sökträd tar i genomsnitt 1) Θ(n) operationer 2) Θ(n log n) operationer 3) Θ(n 2 ) operationer b) Att göra inlägg av n slumptal i ett från början tom sorterad lista tar i genomsnitt 1) Θ(n) operationer 2) Θ(n log n) operationer 3) Θ(n 2 ) operationer c) Nyckelordet extends efter klassnamnet i en klassdeklaration anger att d) Nyckelordet implements i en klassdeklaration anger att e) En (effektiv) inordertraversering av ett binärt trädmed n noder tar 1) klassen är en subklass 2) klassen är en basklass 3) klassen är ett interface 1) klassen är en subklass 2) klassen tillhandahåller metoderna i ett eller flera interface 3) klassen är ett interface 1) Θ(1) operationer 2) Θ(log n) operationer 3) Θ(n) operationer 4) Θ(n log n) operationer f) Att sortera med mergesort tar i bästa fall 1) Θ(log n) operationer 2) Θ(n) operationer 3) Θ(n log n) operationer 4) Θ(n 2 ) operationer g) Antag att A är en klass. När medför uttrycket B b = new A(); garanterat ett kompileringsfel? 1) om B är en subklass till A 2) om A är en subklass till B 3) om B är en abstrakt klass 4) om B är ett interface h) Instansvariabeln next finns tillgänglig 1) i alla klasser 2) i klasser som ingår i en länkad lista i) I ett händelsestyrt program är en lyssnare 1) ett objekt 2) en variabel 3) en metod 3) endast i klasser som explicit deklarerar d j) Map i java.util är 1) en abstrakt klass 2) en vanlig ( konkret ) klass 3) ett interface (Godkände även alt 1)
Anmälningskod: A2. Metoderna i list- och trädklasserna använder en gemensam undantagsklass ExamException för att signalera fel. Skriva klart det som fattas i klassen nedan! public class ExamException extends RuntimeException { public ExamException(String msg) { super(msg); A3. Varför är det bra att skriva en egen felklass som ExamException? Kan man inte lika gärna låta metoderna kasta objekt av typen RuntimeException? För att det skall gå att hantera felen. Man vill INTE skriva catch(runtimeexception e) eftersom det finns massor av ohanterbara fel som skulle hamna där. A4. Klassen BasicList innehåller en int size() och en boolean isempty(). Är det någon påtaglig fördel med att använda isempty() i stället för size() == 0? isempty har komplexiteten O(1) medan size har komplexiteten Θ(n). A5. Metoden removefirst i BasicList ska ta bort det första elementet ur listan och returnera dess datavärde. Skriv klart metoden! public int removefirst() { if (first == null) { throw new ExamException("removeFirst: List empty"); else { int result = first.data; first = first.next; return result; A6. Satsen int x = list.removefirst(); kan förorsaka att ett ExamException kastas. Hur ska koden skrivas för att fånga undantaget, ge en utskrift och sedan fortsätta exekveringen med värdet 0 på x? Om inget undantag kastas ska ska x ha det värde som removefirst() returnerade. int x = 0; try { x = list.removefirst(); catch(examexception ee) { System.out.println(ee.getMessage());
Anmälningskod: A7. För att addlast i subklassen Queue skall kunna göras effektivt lägger denna klass till instansvariabeln Node last som ska referera sista elementet i listan. Skriv klart metoden addlast som lägger in ett värde sist i listan! @Override public void addlast(int x) { if (first == null) { first = last = new Node(x, null); else { last = last.next = new Node(x, null); A8. Framför ovanstående metod står @Override. Vad betyder det? Varför är det bra att ange detta? Betyder att metoden överskuggar en metod i basklassen. Om man t ex stavar fel på metodnamnet så får man ett kompileringsfel i stället för obegriplig funktion i programmet. A9. Rita det träd som skapas av main-metoden i klassen BST dvs det träd som erhålles när talen 5, 5, 4, 8, 5, 4, 6, 5 adderas i denna ordning. Ledning: Se add-metoden! A10. Metoden tostring i klassen BST ska returnera en sträng innehållande noderna i trädet i storleksordning. Varje nod representeras av dess key-fält föregånget av ett blanktecken. Se körexemplet! Skriv de satser som fattas! @Override public String tostring() { return ( + tostring(root) + ) ; private static String tostring(node r) { if (r == null) { return ""; else { return tostring(r.left) + " " + r.key + tostring(r.right);
Anmälningskod: A11. Metoden BasicList tobasiclist() ska skapa och returnera en lista med data från trädet i stigande ordning. Metodens komplexitet ska vara O(n) där n är antalet noder i trädet. Skriv klart hjälpmetoden nedan! public BasicList tobasiclist() { BasicList list = new BasicList(); tobasiclist(list, root); return list; private static void tobasiclist(basiclist list, Node r) { if (r!= null) { tobasiclist(list, r.right); list.addfirst(r.key); tobasiclist(list, r.left); A12. Givet följande kod: PriorityQueue pq = new PriorityQueue(); for (int i=1; i<n; i++) { pq.addfirst((int)(math.random()*10000000)); while (!pq.isempty()) { pq.removesmallest(); Hur beror körtiden i genomsnitt av n för a) den första och b) den andra iterationen? Svara med uttryck av typen Θ(f(n)). Motivera svaret! (Skriv på baksidan om du får plats i rutan.) a) addfirst tar konstant tid. Att bygga upp listan (n inlägg) tar alltså Θ(n) tid. b) Tiden för removesmallest är proportionell mot listans längd dvs totalt som är Θ(n 2 ) n + (n 1) + (n 2) +... + 2 + 1 = n(n + 1)/2 Tiden domineras av removesmallest alltså Θ(n 2 )
Del B (för betyg 4 och 5) Svaren till dessa uppgifter skrivs på vanligt skrivningspapper. B1. För att klassen Queue ska fungera korrekt måste även metoderna addfirst och removefirst överskuggas. Skriv dessa! (Obs: addfirst och removefirst ska fungera i klassen Queue) @Override public void addfirst(int x) { super.addfirst(x); if (last == null) { last = first; @Override public int removefirst() { int result = super.removefirst(); if (first==null) { last = null; return result; B2. Metoden tostring i uppgift A10 skulle lägga ett blanktecken framför varje tal Skriv en tostring-metod som lägger ett kommatecken följt av ett blanktecken mellan varje tal! Exempel: (1, 2, 3, 4, 4, 4, 8) public String tostring() { return tobasiclist().tostring(); B3. Skriv metoden public static int getsmallest(basiclist list) i klassen ListTest. Metoden ska, med hjälp av iteratorn, leta upp och returnera det minsta värdet i listan. public static int getsmallest(basiclist list) { int result = list.getfirst(); BasicList.Iterator li = list.iterator(); while (li.hasnext()) { result = Math.min(result, li.next()); return result; B4. Givet följande kod: BST bst = new BST(); for (int i=1; i<n; i++) { bst.add((int)(math.random()*10000000)); while (!bst.isempty()) { bst.removesmallest(); Antag att det tar 1 ms att köra ovanstående kod för n = 10 3. Uppskatta hur lång tid det skulle ta med n = 10 6! Motivera!
Tiden för både add och removesmallest är proportionell mot trädets höjd dvs proportionell mot log n. En övre gräns för n blir då c n log n. Detta ger en uppskattning av c: För 10 6 tal får vi då tiden c 1000 log 1000 = 1 c = 1/3000 c 10 6 log 10 6 = 10 6 6/3000 = 2s B5. I en bilaga finns parsern till en numerisk kalkylator som också kan hantera funktionerna max och min. Så här kan en körning se ut: $ java Calculator Numerical calculator version 2016-10-19 > max(2,5) 5.0 > max(1+sin(1), 2-cos(PI)) 3.0 > max(min(1,2), min(3,7)) 3.0 > max(2) *** Syntax error: Binary function must have two arguments *** The error occurred at token ) just after token 2.0 > max(3,4,5) *** Syntax error: Expected ) *** The error occurred at token, just after token 4.0 Av utrymmesskäl är en del av koden utan betydelse för uppgiften utelämnad. Skriv metoden double function2(string functionname) som hanterar dessa nya funktioner! public double function2(string functionname) { double result = 0.0; if (tokenizer.getchar()!= ( ) { throw new SyntaxException("Function name should be followed by ( "); tokenizer.nexttoken(); double arg1 = assignment(); if (tokenizer.getchar()!=, ) { throw new SyntaxException("Binary function must have two arguments"); tokenizer.nexttoken(); double arg2 = assignment(); if (tokenizer.getchar()!= ) ) { throw new SyntaxException("Expected ) "); tokenizer.nexttoken(); if (functionname.equals("max")) result = Math.max(arg1, arg2); else if (functionname.equals("min")) result = Math.min(arg1, arg2); else throw new RuntimeException("Internal error - unknown function: " + functionname); return result;
Var god vänd!
B6. Så här ser klassdesignen för den symboliska kalkylatorn i den sista obligatoriska uppgiften ut: Sexpr abstract String getname() abstract Sexpr eval(map) abstract int priority() Sexpr diff(sexpr) double getvalue() boolean isconstant() boolean isconstant(double) Atom abstract Unary abstract Binary abstract String tostring() Sexpr operand Sexpr left Sexpr right String tostring() Variable String ident Sexpr eval(map) String getname() Sexpr diff(sexpr) Operator abstract String tostring() int priority()? Function abstract String tostring() Addition Subtraction Multiplication Division Constant Evaluation Sin Assignment double value Quotation Cos Differentiation Sexpr eval(map) String getname() Sexpr diff(sexpr) boolean isconstant() boolean isconstant(double) double getvalue() Negation Sexpr eval(map) String getname() Sexpr diff(sexpr) Exp Log Sexpr eval(map) Abs String getname() Sexpr eval(map) Sexpr diff(sexpr) String getname() Sexpr eval(map) String getname() int priority() Vilka ändringar i klassdesignen behöver göras för att även denna skall kunna hantera funktionerna min och max enligt ovanstående uppgift? Rita de delar som behöver ändras eller kompletteras! Se till att alla klasser har passande namn!