Datortentamen i TDP007 2009-03-11 kl. 08-12 ------------------------------------------- Uppgift 1 (4p) -------------- I filen a.rb finns följande klass definierad: class A attr_accessor :val def initialize(in_val) @val=in_val end def set(in_val) @val=in_val end def square val*val end end Betrakta följande körexempel: irb(main):090:0> a=A.new(5) # irb(main):091:0> a.square 25 irb(main):092:0> def a.square; val+val; end nil irb(main):093:0> a.square 10 irb(main):094:0> a2=A.new(4) # irb(main):095:0> a2.square 16 Besvara följande frågor: a) Varför funkar det att använda val och inte @val i metoden square? (1p) b) Beskriv vad som händer på raden märkt 92 i körexemplet ovan! (1p) c) Vilka för- och nackdelar ser du med att man i Ruby kan göra det som åsyftas i fråga b? (1p) d) Vad kan man göra för att förhindra att någon gör som i rad 92? (1p) Uppgift 2 (6p) -------------- a) Konstruera ett reguljärt uttryck som kan matcha olika stavningar av efternamnet "Karlsson", med "C" eller "K" i början, med ett eller två "s", eller med "z". (1p) b) Skapa en klass Button som representerar en knapp som kan slås på och av. När man skapar ett objekt får man ange ett kodblock som ska köras varje gång knappen slås på. Knappen är av när den skapas. Följande exempel visar hur det kan se ut: >> b=Button.new { puts "The heat is on. The heat is o-on." } => ... >> b.push The heat is on. The heat is o-on. => nil >> b.push => nil >> b.push The heat is on. The heat is o-on. => nil Skriv kod som definierar klassen Button. (2p) b) I filen studenter.txt finns information om en grupp studenter. Skriv en funktion som läser in en sådan lista, sorterar studenterna efter efternamn i stigande ordning och skriver ut en lista med endast för- och efternamn. (3p) Uppgift 3 (8p) -------------- I filen tdp007.html finns en webbsida som ursprungligen kommer från LiTH:s studiehandbok och som innehåller kursplanen för den här kursen. Filen har editerats så att den ska gå att parsa som XML. a) Skriv en funktion som kan läsa in filen och med hjälp av reguljära uttryck plocka ut kurskoden ur kursplanen. Du ska *inte* plocka ut kurskoden ur sidans titel som finns först i filen, utan ur tabellen längre ner i filen, i anslutning till kursens namn på svenska och engelska. Det hela är tänkt att funka så här: >> find_code("tdp007.html") => "TDP007" Definiera funktionen find_code (med eventuella hjälpfunktioner). (3p) b) Använd paketet REXML för att parsa filen som XML och hämta sedan ut kurskoden från samma ställe i filen, men med hjälp av t.ex. XPath. Du behöver inte skriva en särskild funktion om du inte vill, utan det räcker att skriva uttryck som utför uppgiften. (3p) c) Baserat på den information som man är ute efter i denna uppgift, diskutera vilken av dessa två metoder som är "bäst". (Du kan få poäng på denna uppgift utan att ha gjort de övriga två.) (2p) Uppgift 4 (5p) -------------- I filen expr.rb finns ett exempel på ett domänspecifikt språk för att beräkna matematiska uttryck. Varje rad består av ett variabelnamn följt av ett uttryck som detta ska bindas till. a 7 b 5 c a+3 # 10 d c*b*2 # 100 e d-7 # 93 De första två raderna binder först a till 7 och b till 5. Nästa rad beräkna a+2 till 10 och binder detta till c. Fjärde raden beräknar c*b*2 till 100, vilket sparas i d. Sista raden beräknar d-7 till 93, vilket binds till e och också blir resultatet av hela beräkningen. Din uppgift är att skriva kod som med hjälp av någon av de tekniker för domänspecifika språk som vi arbetat med läsa in och beräkna den här typen av uttryck. Så här skulle det kunna se ut: >> Expression.calculate("expr.rb") => 93 Uppgift 5 (4p) -------------- Du ska arrangera en middag för åtta inbjudna personer: Kalle, Pelle, Nisse och Janne samt Anna, Disa, Lisa och Tina. Du vill placera dem i par (kille och tjej) på lämpligt sätt, men det finns några konstellationer att undvika. Pelle och Lisa är tillsammans, liksom Kalle och Anna. Därför vill du inte placera dem ihop. Pelle har dessutom varit ihop med Tina tidigare, och därför bör du inte placera dem ihop. I filen amb_test.rb hittar du ett problemlösarverktyg där man med hjälp av s.k. continuations kan specificera problem deklarativt. Använd denna teknik för att hitta ett bra sätt att bilda par inför middagen. Din lösning ska utgå från exemplet, men vara så generell att den lätt går att återanvända för en annan middag med godtyckligt antal deltagare (dock lika många av varje kön). Uppgift 6 (5p) -------------- Om man vill skriva ut saker snyggt kan man använda formatterad utskrift med t.ex. funktionen format. Man börjar med en s.k. formatsträng, som innehåller olika koder för vad som ska skrivas ut och hur det ska se ut. Exempel: >> format("%08b '%4s'", 123, 123) => "01111011 ' 123'" Formatsträngens koder i exemplet ovan talar om att första argumentet (talet 123) ska skrivas ut i binärform med åtta tecken och fyllas ut med nollor vid behov. Vidare ska nästa argument (också talet 123) skrivas ut som en högerjusterad sträng med totalt fyra tecken. I denna uppgift ska du utgå från den parser som vi arbetat med i kursen och som finns i rdparse.rb. Du ska skriva en ny parser som kan tolka ett mycket begränsat utbud av formatsträngar. Detta är ett exempel på hur din kod ska funka: >> fp=FormatParser.new => >> fp.format("Hello %s! %d is %x in hex.", "Peter", 42, 42) => "Hello Peter! 42 is 2a in hex." Du ska alltså implementera en ny parser FormatParser som har en metod format som tar en formatsträng och ett godtyckligt antal extra parametrar. Formatsträngen ska parsas och följande koder kan användas: %s Skriv ut motsvarande argument som en sträng %d Skriv ut motsvarande argument som ett tal %x Skriv ut motsvarande argument som ett hexadecimalt heltal Redovisa koden för FormatParser samt eventuella ändringar i originalparsern.