Fiktiv eksamensbesvarelse IN 211 høsten 2001 Kandidat 1 6. desember 2001 Oppgave 1: Kjøresystemer 1a: Statisk og dynamisk link egne aktiveringsstakken før kallet på P 1b: Parameteroverføring 1. Verdioverføring: 2 blir skrevet ut. Dette er fordi call by value behandler formelle parametre som lokale variable som kun er synlig innenfor sitt eget skop. Name-overføring: P ser da ut som: (i vårt kall) void P(int x, int y, int z) a = a + 1; a = a + a + b; Verdien av a blir da 9. (Siste tilordning i P() gir a = 3 + 3 + 3;) Dermed blir 9 skrevet ut. (Name-overføring bytter ut tekstlig parameteren som vist) 1
2. Anta nå at kallet på P erstattes av kallet P(b,a,a) Referanse-overføring Med referanse-overføring blir adressen til variablene sendt som parameter. Når man f.eks. i P() sier y = y + 1; Så, fordi y nå peker på samme minne-lokasjon som main s a, er det main s a som blir endret. Verdi-resultat Her blir resultatet etter kjøringen av P() kopiert tilbake til kalleren (motsatt av verdi-overføring). Men verdien blir også sendt med inn til P(), så 6 blir skrevet ut. 3. Vi skal svare på hvorfor det er problematisk å tillate kallet P(a + b, a, a) ved referanseoverføring: Her sender vi altså med minnelokasjonene til variablene. Men det finnes ingen variabel som heter (a + b), så man vil få merkelig resultat ved f.eks. at kallet sender referanse til siste variabel b eller noe slikt. Man må kanskje lage en temporær variabel i minne, tilordne denne verdien (a + b), så bruke denne. Uansett vil ikke dette referere til en variabel. verdi-resultat: Resultat-overføring krever at vi etter metodens slutt skal kopiere verdiene (resultatet fra metoden) tilbake til kallerens miljø. Men det finnes ingen variabel som heter (a + b). Dette vil være et problem. Merk: Selve verdioverføringen vil ikke by på problemer. 2
1c: Objekter 3
Oppgave 2: Prolog-grammatikk 2a: Syntaksmengder meta-til-tom startmengde etterfølgermengde statmt NEI name fact NEI name pred NEI name :-. rule NEI name arglist NEI arg [ ) list NEI [ ) ] listelems JA arg ] 2b: Ikke LL(1) Produksjon Utvidet st.mengde. Disjunkt? statmt fact name NEI statmt rule name fact pred. name JA pred name [( arglist )]? name JA rule pred? :- body. name JA arglist arg arg arglist arg, arglist arg NEI arglist list [ listelems ε ] listelems arg arg NEI listelems arg I list arg listelems arg I var arg Den er ikke LL(1) da den ikke har disjunkte utvidede startmengder for de forskjellige produksjonene. 4
Oppgave 3: Regulære uttrykk 3a: Regulært uttrykk beløp beløp2 beløp2 beløp2. beløp3 beløp3 beløp4 beløp4 beløp5 beløp5 beløp6 beløp6. beløp3 3b: Ikke-deterministisk automat. X. 3c: Deterministisk automat. X. X 5
Oppgave 4: Bussruter i ML 4a: Funksjonen steder fun steder(nr:int, rh:rutehefte):string list = case rh of nil => [] (i,j) :: rh => if i = nr then j else steder(nr,rh ); 4b: Funksjonen busser Hjelpemetode: fun finnstopp(s:string, l:list):bool = case l of nil => false x :: l => if x = s then true else finnstopp(s,l ); fun busser(st:string, rh:rutehefte):int list = case rh of nil => 0 (i,j) :: rh => if finnstopp(st,j) then [i] :: busser(st,rh ) else busser(st,rh ); 4c: Ny bussrute fun leggil(nr:int, ss:string list, rh:rutehefte):rutehefte = case rh of nil => [(nr,ss)] (i,j) :: rh => if i = nr then (nr,ss) :: leggil(nr,ss,rh ) else (i,j) :: leggil(nr,ss,rh ); 4d: Nedlegging av stoppested Hjelpemetode: fun fjernstopp(s:string, l:string list):string list = case l of nil => [] x :: l => if x = s then fjernstopp(s,l ) else x :: fjernstopp(s,l ); fun fjern(st:string, rh:rutehefte):rutehefte = case rh of nil => [] (i,j) :: rh => (i, fjernstopp(st,j)) :: fjern(st,rh ); 4e: Bytte mellom busser For å løse oppgaven må man vha fun busser finne ut hvilke busser som stopper på sted A og hvilke som stopper på sted B. Deretter må man for hvert element i intlisten (returnert fra busser) finne listen av stoppesteder ved hjelp av fun steder. Ved så å ta ut det første elementet i stoppestedliste A og sml. denne stringen med alle stringene i liste B kan man finne ut om man kan bytte, og dermed komme frem til ønsket mål. 1. hvilke busser stopper på Kjelsås,A int list med bussnr hvilke busser stopper på St.hanshaugen,B int list med bussnr 2. finn alle stoppestedene til busser som stopper på Kjelsås,A list list finn alle stoppestedene til busser som stopper på St.hansh,A list list 3. sammenligne første elementet i A s indre liste med alle elementene i B s liste 6
4f: Implementasjon ved funksjonsrom type rutehefte = int -> string list; exception nodata; val tom : rutehefte = fn(y) => raise nodata; Steder fun steder(nr,rh) = fn(y) => if nr = y then (rh nr handle nodata => []) else rh y; leggil fun leggil(nr,ss,rh) = fn(x,y) = if (nr,ss) = (x,y) then fjern fun fjern(st,rh) = let val x = rh st in if x = " " then raise nodata else fn(y) => if x = y then " " else rh y 2. Når man implementerer vha funksjonsrom mister man muligheten til å lage en metode som finner ønsket informasjon. Dette fordi man ikke kan søke gjennom et funksjonsrom. Dette skyldes at data ikke oppbevares i datastrukturer slik som lister e.l men i funksjonene selv. 7
Busser i Prolog 5a: Oppslag?- stopper(x,helsfyr). 5b: Knutepunkter knute(x) :- stopper(y,x), stopper(z,x), Y \== Z.?- knute(x). nygård, teisen, helsfyr, teisen, helsfyr, nygård Prolog starter på første fakta, plukker ut stedsnavn, og ser om det finnes et som er likt, med et annet nr. Alle stedsnavnene kommer to ganger siden f.eks og stopper(23,nygård), stopper(37,nygård), 23 \== 37 stopper(37,nygård), stopper(23,nygård), 37 \== 23 ikke sees på som samme tilfelle. 5c: Reiserute (X:nr, Y:nr, Z:sted, V:sted) ettbytte(x,y,z,v) :- stopper(x,z), stopper(y,v), stopper(x,w), stopper(y,w), X \== Y. De to første stopper(... ) skal avgjøre om bussene går til stedene som er angitt, og de to neste om de har et felles stoppested. F.eks. vil?- ettbytte(x,y,lysaker,helsfyr). gi X=23 og Y=37.?-ettbytte(37,X,lysaker,helsfyr). vil derimot gi no. For å rette på dette kan man ha enda en ettbytte(x,y,z,v)-regel, hvor de første to stopper er byttet (stopper(x,v), stopper(y,z)). 8