TDDC74 Programmering: Abstraktion och modellering Datordugga 2 - exempel Läs alla frågorna först och bestäm dig för i vilken ordning du vill lösa uppgifterna. Uppgifterna är inte nödvändigtvis i svårighetsordning. Använd väl valda namn på parametrar och indentera din kod. Väl valda namn inkluderar bland annat konsekvent språk. Du behöver inte skriva kodkommentarer, annat än för väldigt svårförklarade hjälpfunktioner (som bör undvikas). Namngivning ska vara tillräcklig (och följa konventioner). Skriv inte onödigt komplicerade lösningar. Om det är naturligt, definiera gärna hjälpfunktioner! Hjälpfunktioner ska som vanligt lösa tydliga och lättförklarade uppgifter. Du får använda alla tillgängliga primitiver och språkkkonstruktioner i Racket, om annat inte anges i uppgiftstexten. Frågor Är något otydligt i uppgifterna kan du använda meddelande-funktionen i tentaklienten för att skicka frågor till rättande lärare. Att lämna in Skicka in uppgifterna med hjälp av tentaklienten, när du är klar med dem! Du får svar via klienten när din uppgift är rättad. Vänta inte på att alla uppgifter är klara med att lämna in. När du har lämnat in en uppgift, fortsätt arbeta på nästa. Du har en inlämning per uppgift (så skicka inte ev a- och b-uppgifter separat). Följ funktionsnamnen som står i uppgifterna, och testa att alla körexempel i uppgiften fungerar exakt som de är inskrivna! Din totalpoäng på duggan ges som summan av lösningar du lämnat in i tid, oavsett om de hinner rättas klart inom skrivtiden eller ej. Betyg Det finns två duggor i kursen. På varje dugga kan man få som mest 15p. Totalpoängen avgör slutbetyget i kursen. För trea räcker 50% av det totala poängen. Ett resultat man inte är nöjd med, kan plussas vid tentamenstillfället i juni. Lycka till!
Uppgift 1, Omgivningsdiagram (3 poäng) Följande sekvens av uttryck evalueras. På nästa sida finns det tre omgivningsdiagram med två fel i vardera. Påpeka vad som är fel i varje diagram. Du behöver inte redogöra för varför det är fel, det räcker med att påpeka felen. Lämna in dina svar i filen uppg1.rkt. På de riktiga duggorna kommer vi att numrera varje objekt i diagrammen så att du kan referera till dessa i ditt svar. (define state 0) (set! state (+ state 1)) (define f (lambda (state) (- state 1))) ((lambda (state) (* state 2)) 1) (f 1) (let ((state 0)) (lambda () (set! state (+ state 1)))) 2
A: 2 fel GE CE state: 0 1 f: CE2 CE3 CE4 state: 0 state: 1 state: 0 Body: (- state 1) Body: (* state 2) Para: () Body: (set! state Body: (lambda () ) (+ state 1)) B: 2 fel GE CE state: 0 1 f: CE2 CE3 CE4 state: 1 state: 1 state: 0 1 Body: (- state 1) Body: (* state 2) Body: (lambda () ) Para: () Body: (set! state (+ state 1))
C: 2 fel GE CE state: 0 1 2 f: CE2 CE3 CE4 state: 1 state: 1 state: 0 Body: (- state 1) Body: (* state 2) Para: () Body: (set! state Body: (lambda () ) (+ state 1))
Uppgift 2, Dataabstraktion (4 poäng) I matematiken stöter vi på polynom, som exempelvis p(x) = 8x 3 + 7x 2 + 6x + 5. Vi vill nu skapa en abstrakt datatyp poly som representerar ett polynom. När vi skapar polynomet anger vi helt enkelt dess lista av koefficienter, där vi börjar med konstanttermen. p ovan skulle alltså ha koefficient-listan (5 6 7 8), och polynomet q(x) = x 4 + 3x 2 + 7 skulle ha listan (7 0 3 0 1). Det sista ser vi kanske tydligare om vi skriver ut det som q(x) = 1x 4 + 0x 3 + 3x 2 + 0x 1 + 7x 0. Ett polynoms grad (en: degree) är den högsta förekommande exponenten. p(x) har grad 3, r(x) = 5 har grad 0. Lämna in dina svar i filen uppg2.rkt. a) Din uppgift är att implementera poly-typen, och dessa fyra funktioner: En konstruktor make-poly som tar en lista av koefficienter och skapar ett polynom. Vi kan anta att användaren anger polynom utan avslutande nollor (så p(x) ovan skapas alltid med listan (5 6 7 8), och inte t ex (5 6 7 8 0 0 0... )). Ett predikat poly? som kontrollerar om ett objekt är ett polynom 1. poly-degree tar ett polynom och returnerar dess grad. poly-coeff tar ett polynom och en exponent k (k 0 heltal), och returnerar koefficienten framför termen x k. Så här ska det fungera: > ( define p (make - poly (5 6 7 8))) > ( poly? (5 6 7 8)) ;; var listan ett polynom? #f > ( poly? p) ;; blir det vi skapade ett polynom? #t > (poly - degree p) 3 > ( poly - coeff p 3) ;; ge mig koefficienten vid x ^3 8 > ( poly - coeff p 5) ;; ge mig koefficienten vid x ^5 0 OBS! Du kan ha hjälp av funktionen list-ref, som givet en lista och ett index i (0,...) returnerar elementet på plats i. (list-ref (a b c) 1) => b. 1 Korrekt utdata från make-poly. Du behöver inte kontrollera att användaren gjort rätt när de anropade make-poly. 5
b) Polynom av en variabel kan såklart adderas, och bildar då nya polynom. Om vi till exempel lägger ihop p(x) = 8x 3 + 7x 2 + 6x + 5 och q(x) = x + 95, får vi det nya polynomet 8x 3 + 7x 2 x + (6 + 1)x + (5 + 95) = 8x 3 + 7x 2 + 7x + 100. Mer allmänt, skrivs polynom som summor av termer på formen c k x k. När vi adderar två polynom p(x), q(x) går vi igenom dem term för term, och låter koefficienten framför x k i det nybildade polynomet bli summan av koefficienten framför x k i p(x) och koefficienten framför x k i q(x). 2 Din uppgift är att skriva en funktion add-poly som tar två polynom och returnerar ett nytt polynom som är summan av polynomen. Tänk på att du inte får anta något mer om polynomet än att funktionerna ovan (i 5a-beskrivningen ovan) kan användas. Så här ska det fungera: > ( define p (make - poly (5 6 7 8))) ;; p som ovan > ( define q (make - poly (95 1))) ;; q(x) = x + 95 > ( define h (add - poly p q));; h(x) = 8x^3 + 7x^2 + 7x + 100 > (poly - degree h) 3 För full poäng, notera särskilt: > ( define r (make - poly (1 2-7 -8))) > ( define s (add - poly p r)) ;; s(x) = 8x + 6 > (poly - degree s) 1 2 Om polynomen har olika grad, antar vi att koefficienter som saknas är 0. 6
Uppgift 3, Tillståndsmodellering med objekt (4 poäng) Vi vill representera ett minne mem för siffror, där varje minne ska ha koll på just sitt eget värde. Det ska hantera kommandona add, sub, reset och recall. Lämna in dina svar i filen uppg3.rkt. Så här ska det fungera: > (define m1 (make-mem)) > (define m2 (make-mem)) > (m1 add 10) 10 > (m2 add 10) 10 > (m1 sub 5) 5 > (m1 add 2) 7 > (m1 reset) 0 > (m2 recall) 10 > (m1 recall) 0 Skriv make-mem. 7
Uppgift 4, Muterbara struturer (4 poäng) Du får två dataabstraktioner, en för en struktur som heter Triple och en för Deque. Elementen i en deque representeras som en Triple. Din uppgift är att använda den givna dataabstraktionen och skriva en procedur deq-insert-front! 3 som tar två argument (deq-insert-front! dq value) och lägger andra argumentet som ett nytt element i början av dequen dq. Din procedur ska ändra i själva dequen (snarare än att returnera en ny deque med liknande innehåll). Om du är osäker, är ett tips att rita upp hur den länkade strukturen ser ut, och vilka ändringar som genomförs. Tentavakterna har kladdpapper. Du behöver inte lämna in dem. Testa din kod genom att skriva: (define deque (deq-make)) (deq-insert-front! deque eva) (deq-insert-end! deque adam) (deq-insert-front! deque helena) (deq-insert-end! deque carl) (deq-insert-end! deque lisa) Till din hjälp har du en del kod given, som beskriver hur abstraktionen ska fungera. Du får inte ändra i den. Koden nedan finns i filen uppg4-givet.rkt på din tentadator, så du kan kopiera därifrån. För översikts skull finns den även angiven här: ; Följande dataabstraktion skapas för strukturer med tre element (define (triple-make left middle right) (mcons left (mcons middle right))) (define (triple-left triple) (mcar triple)) (define (triple-middle triple) (mcar (mcdr triple))) (define (triple-right triple) (mcdr (mcdr triple))) 3 Titta på materialet i föreläsning 8 och 9. Lösningen finns i kodexmplen för föreläsning 9. Innan du tittar på lösningen där försök förstå hur en Deque är uppstrukturerad och sedan implementera din lösning och jämför med lösningen i kodexemplen. 8
(define (triple-set-left! triple element) (set-mcar! triple element)) (define (triple-set-middle! triple value) (set-mcar! (mcdr triple) value)) (define (triple-set-right! triple element) (set-mcdr! (mcdr triple) element)) ; Handling double ended queues (define (deq-make) (mcons () ())) (define (deq-empty? dq) (null? (mcar dq))) (define (deq-singleton? dq) (eq? (deq-front dq) (deq-end dq))) ;deque has no elements? ;deque has only one element? (define (deq-front dq) (mcar dq)) (define (deq-set-front! dq element) (set-mcar! dq element)) (define (deq-end dq) (mcdr dq)) (define (deq-set-end! dq element) (set-mcdr! dq element)) (define (deq-show dq) ; Denna procedur skapar en lista av elementen i en deque DQ och ; och därmed kan användas för se vad som finns i dequen DQ (define (iter elements) (cond ((null? elements) ()) (else (cons (triple-middle elements) (iter (triple-right elements)))))) (if (deq-empty? dq) () (iter (deq-front dq)))) 9
;; saknades tidigare (enbart för testning, inte del i uppgiften egentligen) (define (deque-insert-end! dq value) (let ((new-triple (triple-make () value ())) (end-element (deque-end dq))) (cond ((deque-empty? dq) (deque-set-front! dq new-triple) (deque-set-end! dq new-triple)) (else (triple-set-left! new-triple end-element) (triple-set-right! end-element new-triple) (deque-set-end! dq new-triple))))) 10