INF3110/4110 L?sningsforslag uke 36 (3.-5.9.2003) Oppgave 1 (Oppgave 1.3 fra l?reboka) --------- Et mulig eksempel ser slik ut: #include int y; int fun(int i) { y++; return i; } int main(void) { int x, z; z = 3; y = 2; x = fun(y) + z + fun(y); /* Opprinnelig setning */ printf("%d\n",x); y = 2; x = 2*fun(y)+z; /* Fors?k p? optimalisering */ printf("%d\n",x); } Den f?rste print-setningen vil skrive ut 8, mens den andre vil skrive ut 7. En slik optimalisering kan heller ikke gj?res i Java. C-programmet over kan oversettes til: class Test{ static int y; public static void main(String[] args) { int x, z; z = 3; y = 2; x = fun(y) + z + fun(y); System.out.println(x); y = 2; x = 2*fun(y) + z; System.out.println(x); } static int fun(int i) { y++; return i; } } Ogs? her vil print-setningene skrive ut henholdsvis 8 og 7. Oppgave 3 --------- Alt unntatt levetiden til klasseobjektene er statisk kjent. N?r det gjelder pekere, har vi at typen til _pekerne_ er bestemt statisk, mens typen til _objektene_ som pekerne peker p?, ikke kan bestemmes f?r programmet kj?rer. Levetiden til objektvariable samsvarer med levetiden til objektene disse befinner seg i. Oppgave 4 --------- Fra deklarasjonen Hele blokken Ytre Indre Ytre Indre x y x y x y x y BEGIN | | VAR x, y; | | | | | | | | PROCEDURE P; | | | | BEGIN | | | | PROCEDURE Q; | | | | BEGIN | | | | VAR y; | | | | | | | | PRINT x; | | | | END Q; | | | | | | | | VAR x; | | | | | | | | x := 2; y := 3; | | | | CALL Q; | | | | END P; | | | | | | | | x := 1; | | | | CALL P; | | | | END Her ser vi at det blir skrevet ut 1 n?r deklarasjonens skop starter ved deklarasjonsstedet, og 2 n?r skopet er hele blokken. Hvis x hadde v?rt dynamisk bundet hadde det blitt skrevet ut 2. Oppgave 5 --------- Et lite eksempel: BEGIN VAR x; x := 1; BEGIN PROCEDURE P; BEGIN PRINT x; END; VAR x; x := 2; BEGIN VAR x; x := 3; CALL P; END; END; END; Oppgave 6 --------- 1. fun flatut(l:LL):L = case l of nil => nil | x::l => x@flatut(l); 2. fun sum(l:L):int = case l of nil => 0 | x::l => x+sum(l); fun summer(l:LL):L = case l of nil => nil | x::l => sum(x)::summer(l); 3. fun sumall(l:LL):int = sum(summer(l)); 4. fun snu(l:L):L = case l of nil => nil | x::l => snu(l)@[x]; fun speil(l:LL):LL = case l of nil => nil | x::l => speil(l)@[snu(x)]; 5. fun insert(l:L,x:int):L = case l of nil => [x] | xx::ll => if xx nil | x::l => insert(sorter(l),x); 6. fun sorterindre(l:LL):LL = case l of nil => nil | x::l => sorter(x)::sorterindre(l); En annen m?te ? gj?re det samme p? er: 1. fun flatut(nil:LL):L = nil | flatut((x::l):LL):L = x@flatut(l); 2. fun sum(nil:L):int = 0 | sum((x::l):L):int = x+sum(l); ... etc. (P? samme m?te for de andre oppgavene.) Oppgave 7 --------- fun settInnSist(x,l) = case l of [] => [x] | y :: r => y :: settInnSist(x,r); En kanskje enklere l?sning er: fun settInnSist(x,l) = l @ [x]; Jobben som m? gj?res blir essensielt den samme, men dette skjules n? av operatoren @ (pr?v ? implementere denne!). Oppgave 8 --------- exception Empty; fun last(l) = case l of [] => raise Empty | x :: r => case r of [] => x | x' :: r' => last(r); Oppgave 9 --------- fun plukk(n,l) = case l of [] => [] | x :: r => if n = 0 then [] else x :: plukk(n-1,r); Det er vilk?rlig om man velger ? teste p? l eller n f?rst. Her er det valgt ? sjekke l f?rst, mens det i neste oppgave testes p? n f?rst. (Dette er tilfeldig valgt.) Oppgave 10 ---------- fun fjern(n,l) = if n = 0 then l else case l of [] => [] | x :: r => fjern(n-1,r);