Uppgift 1: Blandade småfrågor ----------------------------- a) Ge ett bra exempel (som inte finns i boken) på hur man använder metoden Array#inject och förklara vad som händer när man kör det. (1p) b) Antag att vi har en sträng som innehåller namnet på en kurs samt antalet poäng, t.ex. "TDP007 Konstruktion av datorspråk, 6 hp". Konstruera ett reguljärt uttryck som kan plocka ut poängen ur strängen. (1p) c) Vad innebär det att ett XML-dokument är "well-formed" respektive "valid"? (1p) d) När ska man använda strömparsning (SAX) och när ska man använda trädparsning (DOM)? Ge ett exempel på användningsområde och förklara kort varför den ena metoden skulle kunna vara bättre. (2p) Uppgift 2: Enhetstestning ------------------------- I filen test_change.rb finns enhetstester för en funktion give_change. Funktionen är tänkt att räkna ut hur många av varje valör man ska lämna tillbaka i växel för ett visst belopp. Beloppet 22 kr ska t.ex. motsvaras av en tjugokronorssedel och två enkronorsmynt. Funktionen tar ett eller två argument. Första argumentet ska vara det belopp som man vill ha översatt. Andra argumentet ska vara vilka valörer som finns. Default är [100, 50, 20, 10, 5, 1]. Vi räknar enbart med hela kronor (eller vilken valuta vi nu tänker oss). Funktionen returnerar en array som talar om antalet för varje valör. Hur funktionen ska fungera i övrigt framgår av testfallen. Din uppgift är att skriva en funktion som klarar av alla dessa testfall. Uppgift 3: Enhetsomvandling --------------------------- När man läser kakrecept stöter man ofta på en massa hushållsenheter för volym som kan vara svåra att förstå och omvandla mellan, framför allt måtten tsk (tesked) och msk (matsked) som ju inte är standardiserade SI-enheter. Följande omvandlingstabell är därför bra att känna till: 1 tsk = 5 ml 1 msk = 15 ml 1 dl = 100 ml 1 l = 1000 ml Du ska nu definiera en klass för att hantera omvandling mellan alla de fem enheter som finns i tabellen ovan. Ett objekt av klassen ska innehålla en viss volym, som ska kunna skapas, ändras och hämtas i en önskad enhet. Följande exempel visar ungefär hur det är tänkt att funka: >> v = Volume.new(5,"msk") # Skapa ett objekt med volymen 5 msk => # >> v.get("dl") # Vad motsvarar 5 msk i dl? => 0.75 >> v.get("ml") # Vad motsvarar 5 msk i ml? => 75.0 >> v.set(4,"msk") # Ändra volymen till 4 msk istället => ??? >> v.get("tsk") # Vad blir 4 msk i tsk? => 12.0 Tecknen ??? ovan markerar att returvärdet är ointressant. Förutom att definiera metoderna get och set så att de funkar enligt ovan ska du också definiera en klassmetod is? som tar en sträng. Metoden ska svara true om strängen är en giltig beskrivning av en av de fem enheterna ovan och false i alla andra fall. För att underlätta enhetsomvandlingen kan du t.ex. se till att internt i volym-objektet alltid lagra volymen i en och samma enhet. Uppgift 4: Kan jag baka en kaka? -------------------------------- Om man ska baka en kaka måste man ha tillräckligt med ingredienser hemma. Du ska nu definiera en funktion som kan kontrollera detta. Funktionen ska ta in två hash-tabeller: en som talar om vad som ingår i receptet och en som talar om vad som finns hemma. Som exempel kan vi ta följande: my_things = {"cocoa"=>[5,"dl"],"sugar"=>[0.5,"l"], "milk"=>[1,"dl"],"water"=>[1000,"l"]} chocolate_sauce = {"cocoa"=>[1,"dl"],"sugar"=>[1,"dl"],"water"=>[1,"dl"]} chocolate_drink = {"cocoa"=>[1,"msk"],"sugar"=>[1,"msk"],"milk"=>[2,"dl"]} Den första tabellen är vad vi har hemma och de två sista är recept. Som framgår av exemplet är varje ingrediens en sträng vars värde i tabellen är en array som talar om hur mycket som finns respektive behövs. Du ska definiera en funktion can_bake? som ska funka ungefär så här: >> can_bake?(chocolate_sauce,my_things) => true >> can_bake?(chocolate_drink,my_things) Needed at least 2dl of milk but found 1.0dl. => false Felutskriften behöver inte se ut exakt så här, så länge all nödvändig information finns med. Observera att du kan komma att behöva omvandla mellan enheter. Du ska då återanvända klassen från föregående uppgift, så att du kan jämföra och komma fram till att t.ex. 1 dl är mindre än 100 l. Om en ingrediens som krävs inte finns med i skafferiet alls måste det också tas omhand. Uppgiften kan lösas (men inte testas) utan att föregående uppgift är löst. Uppgift 5: Vilka kakor kan jag baka? ------------------------------------ I filen supply.xml finns en lista i XML-format över alla ingredienser som Kalle har hemma, och i filen cake.xml finns ett antal recept på olika kakor. Frågan är om Kalle kan baka någon av dessa kakor. Din uppgift är att skriva ett program som kan läsa in dessa två XML-filer, jämföra recepten med vad som finns hemma och tala om vilka kakor som Kalle kan baka. Tanken är givetvis att du ska återanvända funktionen can_bake? från föregående uppgift. Det innebär också att du måste läsa in ingredienslistorna till det format som can_bake? vill ha. >> check_recipes("cake.xml","supply.xml") Now checking Sockerkaka OK Now checking Tigerkaka Needed at least 200g of butter but found 150g. Now checking Banankaka OK => ??? Vad funktionen returnerar är inte intressant. Utskriften behöver inte se ut exakt så här, så länge samma information finns med. Uppgiften kan lösas (men inte testas) utan att föregående uppgift är löst. Lösningen ska fungera på godtyckliga XML-filer, dvs den ska fungera för vilka filer som helst som har samma format, inte bara just de här kakorna.