TDP007 Konstruktion av datorspråk Hemtentamen 2008-08-20 Hemtentamen är kompletterings- och omexaminationstillfälle för de studenter som missat hela eller delar av inlämningar och seminarier, moment LAB1, 2 hp. Allmänna instruktioner och filer som behövs finns på http://www.ida.liu.se/~tdp007/material/hemtenta/ Lösningar på denna hemtentamen ska skickas via e-post till Peter Dalenius, petda@ida.liu.se, senast torsdag 21 augusti kl 12.00. Uppgifter markerade med Inlämning är avsedda att komplettera inlämningar. Dessa uppgifter är konstruktionsuppgifter som innebär att du ska producera programkod, enhetstester och programmeringsdagbok. Samma förutsättningar som för inlämningarna gäller, dvs du kan bli godkänd även om programmet inte är helt perfekt om du har gjort en tillräcklig bearbetning av problemställningen. Uppgifter markerade med Seminarie är avsedda att komplettera seminarierna. Dessa uppgifter går oftast ut på att du ska sätta dig in i programkod och förklara vad den gör, eller kommentera olika möjliga lösningar. För varje uppgift kommer du få en eller flera uppgifter som ska besvaras i text. Du behöver alltså inte lämna in någon programkod. Inlämning 1: Grundläggande Ruby Vi har sett hur man i Ruby kan skicka kodblock som ett slags extra argument till många metoder. Vi kan också själva skapa metoder som kan ta hand om kodblock. Jämför t.ex. följande två metoder: def f1 &a a.call def f2 a a.call Den första varianten kan vi anropa med ett kodblock som vanligt genom t.ex. f1 {puts "Hej"} men detta funkar inte för den andra varianten. Eftersom a i det fallet är en vanlig parameter måste vi se till att blocket omvandlas till ett Proc-objekt. Det kan vi göra genom att låta det föregås av Proc.new eller lambda. Vi kan alltså skriva era av f2 Proc.new {puts "Hej"} f2 lambda {puts "Hej"} Den här tekniken kan vi använda oss av om vi vill skicka flera olika block till en metod. Som ytterligare stöd för detta behöver vi metoder som kan operera på Proc-objekt. Mer specifikt vill vi i den här uppgiften ha två metoder repeated och compose. 1 (5)
Den första metoden repeated ska ta ett Proc-objekt samt ett positivt heltal och skapa ett nytt Proc-objekt som innebär att man upprepar den givna funktionen så många gånger som angivits. Om man skickar in funktionen f(x) ska alltså resultatet bli f(f(f( f(x)))) dvs funktionen upprepad n gånger. Följande två testfall kan tjäna som utgångspunkt. repeated(lambda { x x*x}, 2).call(5) # ger svaret 625 repeated(lambda { x x+1}, 7).call(5) # ger svaret 12 Den andra metoden compose ska ta två Proc-objekt och utföra funktionskomposition. Om de två funktionerna är f(x) och g(x) ska resultatet alltså vara f(g(x)). Följande testfall kan tjäna som utgångspunkt. compose(lambda { x x+1}, lambda { y y*2}).call(3) # ger svaret 7 Glöm inte att bifoga enhetstester (som även testar andra fall utöver ovanståe) samt programmeringsdagbok. Seminarie 1: Grundläggande Ruby Följande metod gör något med talen i intervallet a till b, men vad? Förklara vad poängen är med programkoden och vad man kan ha den till. Koden finns också i en fil på hemsidan. def acc comb, null_value, term, a, succ, b if a > b null_value else comb.call(term.call(a),acc(comb,null_value,term,succ.call(a),succ,b)) Du kan eventuellt behöva läsa igenom föregåe uppgift. Du kan också använda följande testfall för att köra koden. acc(lambda { x,y x+y}, 0, lambda { x x}, 1, lambda { x x+1}, 6) Inlämning 2: Reguljära uttryck och XML Antag att vi har en textfil som innehåller information om ett antal personer. Formatet framgår av följande exempel: marma112:martin:malmström:800113-1234:tnccc_1:tddb46 TDDB80: urbuv120:urban:uv:800121-1234:tnccc_1:tddb46 TDDB80: berbe101:bertil:bertilsson:800102-1234:tnccc_1:tddb46 TDDB80: Vi vill kunna läsa in sådana textfiler så att informationen hamnar i en array av objekt, där varje objekt innehåller information om en person. Inläsningen ska ske med hjälp av reguljära uttryck och vi vill även anpassa utskriftrutinerna så att informationen skrivs ut som XML. Det hela ska fungera enligt följande körexempel: irb(main):1:0> a = StudentList.new <students> </students> irb(main):2:0> a.read("c:/studenter.txt") nil 2 (5)
irb(main):3:0> a[0] <student id="marma112"> <name>martin Malmström</name> <number>800113-1234</number> irb(main):4:0> a <students> <student id="marma112"> <name>martin Malmström</name> <number>800113-1234</number> <student id="urbuv120"> <name>urban Uv</name> <number>800121-1234</number> <student id="berbe101"> <name>bertil Bertilsson</name> <number>800102-1234</number> </students> Redovisa programkod som löser problemet. På kursens webbsidor finns en exempelfil som kan användas för testning. Seminarie 2: Reguljära uttryck och XML I uppgiften ovan förekom två olika format för att lagra information om personer: ett kompakt format med en person per rad samt XML. I vilka situationer kan det ena formatet vara att föredra framför det andra? Varför? Diskutera för- och nackdelarna med respektive format. Hitta gärna på exempel på situationer eller system där för- och nackdelarna illustreras. Ditt svar bör vara omkring 300 ord. Inlämning 3: Parsning, grammatiker och DSL När man står inför uppgiften att på något sätt bearbeta en textfil med data är ett vanligt tillvägagångssätt att använda t.ex. reguljära uttryck. Ett annat sätt, som vi diskuterat i kursen, är att istället betrakta datafilen som programkod och försöka skriva en parser. Vi betraktar alltså datafilen som om den var skriven i ett begränsat domänspecifik språk (DSL). Det finns en del olika tekniker för att göra detta som är särskilt användbara i Ruby. För den här uppgiften ska du bearbeta en textfil som kan se ut så här: flower "Geranium sylvaticum" swedish "Skogsnäva" height 50 color "Purple" petals 5 Filen innehåller information om ett antal växter. Varje växt inleds med en rad med nyckelordet flower. Därefter kan det följa en eller flera rader med olika nyckelord som ger ytterligare information. Dessa kan komma i vilken ordning som helst, ha olika många argument samt börja med vilka nyckelord som helst (förutom flower). Målet är att skapa en array med information om blommorna i filen, där varje blomma ska representeras som en hashtabell med nyckelorden som nycklar. Det finns en längre exempelfil på kurshemsidan att utgå från. 3 (5)
Seminarie 3: Parsning, grammatiker och DSL Beskriv översiktligt vilka olika tekniker i Ruby för att implementera DSL som vi har gått igenom i kursen. Ditt svar bör vara omkring 300 ord. Inlämning 4: Constraint propagation networks Det första exemplet på constraint networks som vi tittade på i samband med seminarium 4 handlade om logiska grindar. Vi hade programkod för AND-, OR- och NOT-grindar och kunde spåra hur de logiska värdena sant och falskt propagerade genom nätverk som vi byggde upp av dessa. När man använder logiska kretsar i praktiken, inom digitaltekniken, är det vanligt att man använder sig av en särskild typ av grindar som kallas NAND. Man kan se det som en kombination av en NOT- och en AND-grind. Sanningstabellen för NAND ser ut så här, där A och B är indata och Q är utdata: A B Q 0 0 1 0 1 1 1 0 1 1 1 0 Bredvid tabellen ser du också symbolen för en NAND-grund. NAND-grinden ger alltså värdet sant (1) för alla indata, utom när A och B båda är sanna. Det fiffiga med NAND-grinden är dels att den är lätt att bygga i hårdvara, dels att man genom att kombinera NAND-grindar på olika sätt kan bygga upp nätverk som motsvarar alla andra grindar. NAND-grindar är alltså det a man behöver ta med sig till en öde ö. Följande tabell visar hur man kan bygga nätverk som motsvarar våra vanligaste grindar, enbart med hjälp av NAND: För att bygga en NOT-grind AND-grind kombinerar man NAND-grindar så här: Kommentar Man låter det a indatat till NOT-grinden gå till båda portarna på NAND-grinden. Man kombinerar två NANDgrindar på detta sätt. OR-grind Man kombinerar tre NANDgrindar (där de två första i praktiken motsvarar NOT). Du ska nu utgå från koden från seminarium 4 (se kurshemsidan) och utöka den med en NANDgrind. Därefter ska du skrota de gamla implementationerna av AND-, OR- och NOT-grindarna och istället implementera dem genom att bygga upp nätverk av NAND-grindar. Utåt sett ska det funka precis som förut, dvs det ska finnas en klass per grindtyp som man ska kunna instansiera med en eller två indatakanaler, samt en utdatakanal. Bifoga också kod och körexempel som visar att du testat koden. 4 (5)
Seminarie 4: Constraint propagation networks För denna uppgift ska du besvara följande frågor: Vad är deklarativ programmering? Förklara begreppet för någon som kan programmera, men aldrig hört talas om det förut, gärna med exempel. Varför är constraint propagation networks ett exempel på deklarativ programmering? Ge en tydlig motivering. 5 (5)