Datalogi, grundkurs 1 Tentamen 9 dec 2014 Tillåtna hjälpmedel: Revised 6 Report on the Algorithmic Language Scheme och Tre olika s.k. Cheat Sheets för Scheme Sex olika s.k. Cheat Sheets för Python Tänk på: Följ noga vaktens instruktioner. Skriv högst en uppgift på varje blad. Använd endast framsidan på varje blad. Uppgifterna kommer inte i svårighetsordning. Skriv tydligt, motivera svaren endast begriplig och läsbar lösning ger poäng. Maximal poäng finns angiven inom parentes vid varje uppgift. Totalt kan tentamen ge 70 poäng, varav 35 säkert ger godkänt. Man kan också samla max 10 extra poäng genom att göra laborationerna innan respektive laborations deadline men man måste ha minst 35 på själva tentan. Lycka till, Fredrika, Alex och Vahid
1. Rutnät Man vill implementera en spelplan som skulle kunna användas till ett antal olika spel bl.a. det kända spelet Schack. Följande krav ska uppfyllas: Spelplanen består av vita och svarta rutor Det finns lika många rader och kolumner i planen En svart ruta som inte ligger i kanten har total 4 vita grannar på horisontella och vartikala ledden samt 4 svarta på diagonala ledden och vise versa. I varje ruta ska det finnas information om färgen och information om rutans status, d.v.s om den är upptagen av en spelpjäs eller inte. I Schack har man en spelplan med 8 rader och 8 kolumner som skulle kunna skapas m.h.a konstruktoren spelplan enligt nedan: >(spelplan 8) (((v _) (s _) (v _) (s _) (v _) (s _) (v _) (s _)) ((s _) (v _) (s _) (v _) (s _) (v _) (s _) (v _)) ((v _) (s _) (v _) (s _) (v _) (s _) (v _) (s _)) ((s _) (v _) (s _) (v _) (s _) (v _) (s _) (v _)) ((v _) (s _) (v _) (s _) (v _) (s _) (v _) (s _)) ((s _) (v _) (s _) (v _) (s _) (v _) (s _) (v _)) ((v _) (s _) (v _) (s _) (v _) (s _) (v _) (s _)) ((s _) (v _) (s _) (v _) (s _) (v _) (s _) (v _))) Där (v _) är en ruta, v står för färgen vit och tecknet _ märker ut att rutan inte är upptagen av någon pjäs. I Schack används siffrorna 1-8 och tecknen A-H för att märka ut raderna respektive kolumnerna i spelplanen. Information om en ruta i spelplanen skulle kunna fås m.h.a selektorn ge_ruta. Ett anrop till ge_ruta för rutan i rad 1 och kolumn A (d.v.s. översta vänstra rutan) ser ut som nedan: >(ge_ruta 1 A (spelplan 8)) (v _) a. (7p) Skriv konstruktorerna ruta och spelplan b. (3p) Skriv selektorn ge_ruta 1 av 5
2. Filläsning i Python På en programmeringskurs finns 5 hemuppgifter och flera övningsgrupper numrerade 1,2,... osv. Vilka studenter som har gjort vilka uppgifter sparas i ett kalkylblad enligt följande: På översta raden i tabellen står uppgifternas poäng. För resterande rader gäller följande: I första kolumnen står elevernas namn, i andra kolumnen står gruppnumret eleverna tillhör och i de efterföljande 5 kolumnerna står en 1:a om eleven har gjort uppgiften och en 0:a annars. Detta kan sedan exporteras till en vanlig textfil i ett format som heter Comma Separated Values (CSV). Alla tabellceller kommer då separeras med semikolon. Filen kommer då se ut som följer (här med endast fyra studenter): 0.3;0.5;1.6;0.7;0.4 Ola;4;1;1;1;1;1 Eva;2;0;1;1;1;1 Ali;3;1;0;1;1;1 Ida;2;1;1;1;1;1 I detta exempel ser vi att uppgifterna ger poängen 0.3, 0.5, 1.6, 0.7 och 0.4 poäng vardera. Vi kan utläsa att Eva och Ida går i grupp 2 medan Ali går i grupp 3 och Ola går i grupp 4. Eva har inte gjort den första uppgiften och Ali har inte gjort den andra. Ola och Ida har gjort alla uppgifter. (10p) Skriv ett pythonprogram som läser textfilen uppgifter.csv och skriver ut på skärmen totalt antal poäng för varje student i grupp 2. Med ovanstående exempel skulle utskriften kunna bli: Eva 3.2 poäng Ida 3.5 poäng Tips: Funktionen split kan vara till stor hjälp i denna uppgift. 2 av 5
3. Collatz problem Bakgrund Collatz problem är en räknelek som går ut på följande: Börja med att välja ett positivt heltal gör sedan följande operation: Om det valda talet är jämnt, dela det på 2. Om det är udda, multiplicera det med 3 och addera med 1. Gör om operationerna på resultaten tills du får talet 1. (Det är ett olöst problem huruvida man faktiskt alltid når 1. Här antar vi att man gör det!) Uppgift Betrakta proceduren collatz nedan. Proceduren tar ett starttal n och producerar hela sekvensen (tills man når 1), som en lista. T.ex. om man börjar med talet 11 får man följande sekvens: > (collatz 11) (11 34 17 52 26 13 40 20 10 5 16 8 4 2 1) Följande kod är alltså given: (define collatz (lambda (n) (define (mul3-inc1 x) (+ (* x 3) 1)) (define (halve x) (/ x 2)) (define (even? x) (= (modulo x 2) 0)) ;;här skulle proceduren choose ha definerats (if (= n 1) (list n) (cons n (collatz ((choose even? halve mul3-inc1) n)))))) a. (7p) Proceduren (choose pred proc1 proc2) tar ett predikat, pred, och två procedurer, proc1 och proc2, som argument och returnerar en ny procedur. Den returnerade proceduren tar ett argument och beroende på om argumentet uppfyller predikatet, applicerar den på proc1 respektive proc2. Skriv proceduren choose så att collatz funkar. b. (3p) Skriv om det rekursiva anropet så att det sker med anonyma procedurer istället för de lokalt definierade procedurerna halve, mul3-inc1 och even?(endast det rekursiva anropet behöver skrivas om). c. (5p) Är collatz svansrekursiv? Motivera noga! Om inte, skriv om den till svansrekursiv. d. (4p) Skriv motsvarande funktion i Python utan att använda rekursion. 3 av 5
4. Vektorer i Python Man har implementerat vektorer i Python och följande funktioner finns redan. Funktionen vector(c1, c2,c3,...) skapar och returnerar en vektor med elementen c1, c2, c3,... Funktionen atcoord(v,idx) ger element på index idx i vektorn v (vektorns index börjar på 1) Funktionen dimension(v) ger vektorns dimension / antal element. Du vet inget om hur dessa funktioner är implementerade och kan alltså inte göra några antaganden om hur vektorn är representerad. Med hjälp av dessa beskrivningar är din uppgift att implementera nedanstående funktioner. Funktionen scalarprod(v1, v2) ger skaläprodukten av v1, v2. Funktionen enorm(v) ger Euklidisk norm av v. Funktionen normalise(v) ger normaliserad version of v. Anta att V1=(a,b) och V2=(c,d). Då gäller följande: scalarprod(v1,v2) ger vektorn vector(a*c, b*d), V1 och V2 måste vara lika stora enorm(v1) ger kvadratroten ur a*a+b*b normalise(v1) ger vektorn vector(a/(a*a+b*b), b/(a*a+b*b)) a. (5p) Implementera scalarprod, enorm och normalise samt skriv även pre-/postvillkor. Tips: vissa procedurer är enklare att skriva efter att andra redan har skrivits. b. (2p) Vad är ett blackbox-test och vem bör utföra ett sådant? c. (3p) Skriv förslag på blackbox-test för funktionerna vector och enorm. 4 av 5
5. Sökning Vladimir har en sorterad lista i stigande ordning som han kallar L. Han vill hitta det största talet i listan som är 20. Han har hört att algoritmen binärsökning kan användas för att lösa problemet. Algoritmen binärsökning lyder: 1- Kolla om listan är tom. Då finns det vi söker inte i listan. 2- Annars börja titta på talet som finns i mitten av listan. 3- Om talet i mitten är större än det vi söker, gör om allt från början fast med första halvan av listan. 4- Annars om talet i mitten är mindre än det vi söker, gör om allt från början fast med andra halvan av listan. 5- Annars talet finns i listan. Men han behöver tillämpa algoritmen så att det kan lösa just hans problem. Vladimir är säker på att listan består av tal som är mindre och större än 20 men det är inte alls säkert om just talet 20 finns i listan. Här är hans försök av binärsökning: (define (binsearch lst X) ;; ska hitta index för största tal <= X i lst (define (bs sta sto) ;; garanterat [sta, sto) (if (= (+ sta 1) sto) sta (let ((mitt (quotient (+ sta sto -1) 2))) (if (>= (list-ref lst mitt) X) ;; är lst[mitt] >= X? (bs sta mitt) ;; då är svaret i [sta mitt) (bs mitt sto))))) ;; annars är det i [mitt sto) (bs 0 (length lst))) (binsearch L 20) a. (5p) Antag att L är (10 15 20). På vilka argument appliceras bs i binsearch? På vilka argument appliceras bs i första anropet av bs? b. (15p) Som det kanske framgår av svaret på föregående fråga, har binsearch en del buggar. Efter många dagars arbete har Vladimir insett att det krävs en ändring på raden (let ((mitt (quotient (+ sta sto -1) 2))) och en på raden (if (>= (list-ref lst mitt) X) för att programmet ska fungera korrekt. Modifiera koden på de två ställena så att den fungerar och motivera varför den gör det. Lösning med stor avvikelse från binärsökning ger max 2 poäng. 5 av 5