Datalogi, grundkurs 1 Lösningsförslag till tentamen 10 december 2008
1. a. Man testar med typiska värden, gränsvärden och värden utanför specificerad indatavärdemängd. Helst med alla permutationer av indata. Ska utföras av någon som inte känner till programkoden, därav namnet. b. Man testar med indata som ska se till att all kod exekveras. Bör utföras av någon med full insyn i programkoden (men helst ska det inte vara programeraren). 2. a. Proceduren interval-list är svansrekursiv eftersom man inte opererar på resultatet av det enda rekursiva anropet. Proceduren remove-multiples är inte svansrekursiv eftersom på else-raden opererar cons på resultatet av det andra av de två rekursiva anropen. Proceduren sieve är inte svansrekursiv eftersom man opererar på resultatet av det enda rekursiva anropet. b. (define prime? (lambda (n) (define interval-list (lambda (m n lst) (if (> m n) lst (interval-list (+ 1 m) n (append lst (list m)))))) (define remove-multiples (lambda (n lst new) (cond ((null? lst) (reverse new)) ((= (modulo (car lst) n) 0) (remove-multiples n (cdr lst) new)) (else (remove-multiples n (cdr lst) (cons (car lst) new)))))) (define sieve (lambda (lst new) (if (null? lst) new (sieve (remove-multiples (car lst) (cdr lst) ()) (append new (list (car lst))))))) (= n (car (reverse (sieve (interval-list 2 n ()) ())))))) 1 av 4
Observera att med min lösning får både remove-multiples och sieve en extra parameter i form av en tom lista. c. Jag har valt att skriva ett felmeddelande för allt som inte är heltal större än 1. Då blir procedurkroppen för prime? så här: (if (and (number? n) (exact? n) (> n 1)) (= n (car (reverse (sieve (interval-list 2 n ()) ())))) (display "prime? kräver tal större än 1\n")))) 3. PROGRAM uppg3(fil); VAR fil : TEXT; n, i : Integer; n := 0; Reset(fil); WriteLn( Filen innehåller: ); WHILE NOT EoF(fil) DO IF fil^ IN [ 0.. 9 ] THEN n := Succ(n); Read(fil, i) END ELSE Get(fil) WriteLn(n:1, heltal ); END. 4. a. CONST minindex = 1; maxindex = 100; TYPE index = minindex..maxindex; vector = ARRAY [index] OF Integer; duger bra, men det gör mycket annat också b. PROCEDURE sort(var v: vector; m, n: Integer); VAR i: Integer; didswap: Boolean; didswap := FALSE; FOR i := n downto Succ(m) DO IF v[i] < v[pred(i)] THEN didswap := TRUE; swap(v[i], v[pred(i)]) IF (Succ(m) < n) AND didswap THEN sort(v, Succ(m), n); 2 av 4
c. PROCEDURE sort(var v: vector; m, n: Integer); VAR i: Integer; FOR m := Succ(m) TO n DO FOR i := n DOWNTO m DO IF v[i] < v[pred(i)] THEN swap(v[i], v[pred(i)]); OBS! att jag valt en version utan den efterfrågade förbättringen. Vill jag ha med den måste jag välja lite annorlunda kod. PROCEDURE sort(var v: vector; m, n: Integer); VAR i : Integer; didswap : Boolean; didswap := TRUE; m := Succ(m); WHILE (m < n) AND didswap DO didswap := FALSE; print(v); FOR i := n downto m DO IF v[i] < v[pred(i)] THEN swap(v[i], v[pred(i)]); didswap := TRUE m := Succ(m); END d. PROCEDURE swap(var i,j : Integer); VAR k : Integer; k := i; i := j; j := k; swap deklareras var som helst i programmet eftersom man endast skickar vektorelementen som argument. 5. a. ;; Konstruktor för post (define make-post (lambda (varunr varutyp pris sort kvantitet) (list varunr varutyp pris sort kvantitet))) ;; Selektorer för poster (define get-varunr (car post))) 3 av 4
(define get-varutyp (cadr post))) (define get-pris (caddr post))) (define get-sort (cadddr post))) (define get-kvantitet (caddr (cddr post)))) ;; Konstruktor för att skapa registret (define create-reg (lambda () ())) ;; Lägg till en post (define add-post (lambda (post reg) (cond ((null? reg) (list (post))) ((= (get-varunr post) (get-varunr (get-first reg))) (cons post (get-rest reg))) (else (cons (get-first reg) (add-post post (get-rest reg))))))) ;; Selektorer för reg ;; Hämta första posten (define get-first (lambda (reg) (if (null? reg) () (car reg)))) ;; Hämta resten (allt utom första posten) (define get-rest (lambda (reg) (if (null? reg) () (cdr reg)))) 4 av 4
b. (define calc-value (lambda (reg) (define post-value (* (get-pris post) (get-kvantitet post)))) (define inner (lambda (reg value) (if (null? reg) value (inner (get-rest reg) (+ value (post-value (get-first reg))))))) (inner reg 0))) 5 av 4