Sample Final Exam Questions - Programming Languages and Compilers | CS 421, Exams of Computer Science

Material Type: Exam; Class: Progrmg Languages & Compilers; Subject: Computer Science; University: University of Illinois - Urbana-Champaign; Term: Fall 2006;

Typology: Exams

Pre 2010

Uploaded on 03/16/2009

koofers-user-dts
koofers-user-dts 🇺🇸

8 documents

1 / 9

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
CS 421, Fall 2006
Sample Final Questions
1. Write a function get primes : int -> int list that returns the list of primes less than or equal the
input. You may use the built-in functions /and mod. You will probably want to write one or more
auxiliary functions. Remember that 0 and 1 are not prime.
Answer: let rec every p l = match l with [] -> true | x::xs -> p x && every p xs
let not_divides n q = not(n mod q = 0)
let rec get_primes n =
match n with 0 -> []
| 1 -> []
| _ -> let primes = get_primes (n-1) in
if every (not_divides n) primes then n::primes else primes
2. Write a tail-recursive function largest: int list -> int option that returns Some of the largest
element in a list if there is one, or else None if the list is empty.
Answer: let rec largest_aux lgst list =
match list with [] -> lgst
| x :: xs -> match lgst with None -> largest_aux (Some x) xs
| Some l ->
largest_aux (if l > x then lgst else (Some x)) xs
let largest = largest_aux None
(* I would also accept *)
let largest list =
List.fold_left
(fun lgst x -> match lgst with None -> Some x
| Some l -> if l > x then lgst else Some x)
None
list
3. a. Give the types for following expressions (you don’t have to derive them):
let first lst = match lst with
| a:: aa -> a;;
let rest lst = match lst with
| [] -> []
| a:: aa -> aa;;
1
pf3
pf4
pf5
pf8
pf9

Partial preview of the text

Download Sample Final Exam Questions - Programming Languages and Compilers | CS 421 and more Exams Computer Science in PDF only on Docsity!

CS 421, Fall 2006

Sample Final Questions

  1. Write a function get primes : int -> int list that returns the list of primes less than or equal the input. You may use the built-in functions / and mod. You will probably want to write one or more auxiliary functions. Remember that 0 and 1 are not prime.

Answer: let rec every p l = match l with [] -> true | x::xs -> p x && every p xs let not_divides n q = not(n mod q = 0) let rec get_primes n = match n with 0 -> [] | 1 -> [] | _ -> let primes = get_primes (n-1) in if every (not_divides n) primes then n::primes else primes

  1. Write a tail-recursive function largest: int list -> int option that returns Some of the largest element in a list if there is one, or else None if the list is empty.

Answer: let rec largest_aux lgst list = match list with [] -> lgst | x :: xs -> match lgst with None -> largest_aux (Some x) xs | Some l -> largest_aux (if l > x then lgst else (Some x)) xs

let largest = largest_aux None

(* I would also accept *) let largest list = List.fold_left (fun lgst x -> match lgst with None -> Some x | Some l -> if l > x then lgst else Some x) None list

  1. a. Give the types for following expressions (you don’t have to derive them):

let first lst = match lst with | a:: aa -> a;;

let rest lst = match lst with | [] -> [] | a:: aa -> aa;;

Answer: first : α list → α rest : α list → α list

Use these types to derive the types for:

b. let rec foldright f lst z = if lst = [] then z else (f (first lst) (foldright f (rest lst) z)) c. foldright (+) [2;3;4] 0

Answer: Once again, I’m making the mistake of asking you to give a type derivation for a declation (which, technically, we didn’t discuss in class) instead of sticking ot just expressions. I will combine (b) and (c) into a single expression for type derivation: let rec foldright f lst z = if lst = [] then z else (f (first lst) (foldright f (rest lst) z)) in foldright (+) [2;3;4] 0 Because of space constraints the proof tree has been broken up into four parts. Let Γ = { first : α list → α, rest : α list → α list }, and Γ′^ = Γ ∪ {foldright : (α → β → β) → (α list) → β → β, f : α → β → β, lst : α list, z : β}.

Let Tree1 =

Γ′^ `f: α → β → β

Γ′^ first: α list → α Γ′^lst: α list Γ′^ first lst: α Γ′^f (first lst): β → β

Let Tree2 =

Γ′^ foldright: (α → β → β) → (α list) → β → β Γ′^f: (α → β → β)

Γ′^ `foldright f: (α list) → β → β

Γ′^ rest: α list → α list Γ′^lst: α list Γ′^ rest lst: α list Γ′^foldright f (rest lst): β → β Γ′^ z: β Γ′^foldright f (rest lst) z: β Let Tree3 =

Γ′^ foldright: (α → β → β) → (α list) → β → β Γ′^(+): int → int → int

Γ′^ foldright (+): int list → int → int Γ′^[2;3;4]: int list Γ′^ foldright (+) [2;3;4]: int → int Γ′^ 0 : int Γ′^ `foldright (+) [2;3;4] 0: int Then we have:

  1. Give the value of the following expression:

let a = 3 in let p x = x * a in let a = 5 in a + (p 7);;

a. assuming static scope (a.k.a. lexical scope): Answer: 26

b. assuming dynamic scope: Answer: 40

  1. For each of the regular expressions below (over the alphabet {a,b,c}), draw a nondeterministic finite state automaton that accepts exactly the same set of strings as the given regular expression.

i) a∨b∨c* ii) ((aba∨bab)c(aa∨bb))* iii) (ab)(c∨)(ba)

  1. Consider the following ambiguous grammar (Capitals are nonterminals, lowercase are terminals): S → A a B | B a A A → b | c B → a | b Give an example of a string for which this grammar has two different parse trees, and give their parse trees.

Answer:

a. “bab” b

l l l l ll

S

A a B

b

b. S → A a B → b a B → b a b S → B a A → b a A → b a b

  1. Write a unambiguous grammar for regular expressions over the alphabet {a, b}. The Kleene star binds most tightly, followed by concatenation, and then choice. Here we will have concatenation and choice associate to the right. Write an Ocaml datatype corresponding to the tokens for parsing regular expres- sions, and one for capturing the abstract syntax trees corresponding to parses given by your grammar. Write a recursive descent parser for regular expressions, producing an option (Some) of an abstract syntax tree if a parse exists, or None otherwise.

Answer: reg ::= a|b|reg ∨ reg|reg reg|reg∗ Atom ::= a|b|(RegExp) Star ::= Atom|Star * Concat ::= Star|StarConcat RegExp ::= Concat|Concat ∨ RegExp type tokens = A_tk | B_tk | LParen | RParen | Star_tk | Or_tk type atom = A | B | Paren of regexp and star = Atom of atom | Star of star and concat = StarAsConcat of star | Concat of (star * concat) and regexp = ConcatAsRegExp of concat | Choice of (concat * regexp)

let rec mk_star (tree, tokens) = match tokens with Star_tk::more_toks -> mk_star (Star tree, more_toks) | _ -> (tree, tokens)

(* Not done yet *) let rec atom tokens = match tokens with (A_tk::rem_toks) -> (Some A,rem_toks) | (B_tk::rem_toks) -> (Some B,rem_toks) | (LParen::more_toks) -> (match regexp more_toks with (Some tree, RParen::rem_toks) -> (Some(Paren tree),rem_toks) | (, rem_toks) -> (None, rem_toks)) | _ -> (None, tokens) and star tokens = match atom tokens with (Some tree, rem_toks) -> (match mk_star (Atom tree, rem_toks) with (stree, toks) -> (Some stree, toks)) | (None, rem_toks) -> (None, rem_toks) and concat tokens = match star tokens with (Some tree, rem_toks) -> (match rem_toks with A_tk:: -> (match concat rem_toks with (Some tree1, more_toks) -> (Some(Concat(tree,tree1)), more_toks)

let rec eval (exp, env) = match exp with

... | IfThenElse (TrueVal, thenclause, elseclause) -> (thenclause, env) | IfThenElse (FalseeVal, thenclause, elseclause) -> (elseclause, env) | IfThenElse (b, thenclause, elseclause) -> let new_b = eval (b, env) in (IfThenElse (new_b, thenclause, elseclause), env) ... | RepeatUntil(c,b) -> (Seq (c, IfThenElse (b, Skip, RepeatUntil(c,b))), env)

  1. Assume you are given the OCaml types exp, bool exp and comm with (partially given) type definitions:

type comm = ... | If of (bool_exp * comm * comm) | ... type bool_exp = True_exp | False_exp | ...

where the constructor If is for the abstract syntax of an if then else construct. Also assume you have a type mem of memory associating values to identifiers, where values are just intergers (int). Further assume you are given a function eval bool: (mem * bool exp) -> bool for evaluating expressions. Write the OCaml code for the clause of eval comm:(mem * comm) -> mem that implements the following natural semantics rules for the evaluation of if then else commands: 〈m, b〉 ⇓ true 〈m, C 1 〉m′ 〈m, if b then C 1 else C 2 〉 ⇓ m′

〈m, b〉 ⇓ false 〈m, C 2 〉m′′ 〈m, if b then C 1 else C 2 〉 ⇓ m′′

  1. Recollect that we may implement thunks as follows:

type ’a thunk_type = Value of ’a | Susp of (unit -> ’a);;

let delay f = let thunk = ref (Susp f) in fun () -> match (!thunk) with | Value a -> a | Susp f -> let result = f () in (thunk := (Value result); result );;

let force f = f ();;

a. What are the types of delay and force? Answer: delay : (unit -> ’a) -> unit -> ’a force : (unit -> ’a) -> ’a

b. Using the above constructions, but not the Lazy module from Ocaml, implement in Ocaml a type of ’a lazy list.

Answer: type ’a lazy_list = Nil | Cons of (’a * (unit -> ’a lazy_list));;

c. Implement the function take: int -> ’a lazy list -> ’a list which returns the first n ele- ments of the lazy list. Answer: let rec take n llst = match n,llst with | ,Nil -> [] | 0, -> [] | _,(Cons(x,xs)) -> x :: take (n-1) (force xs);;

d. Create an infinite lazy list whose elements are the successive even numbers starting with 0. Answer: let rec map f l = match l with Nil -> Nil | Cons (x,xs) -> Cons (f x, delay (fun () -> map f (force xs))) let rec evens = Cons(0, (fun () -> map ((+) 2) evens))

  1. Write a function dividek n lst k, using Continuation Passing Style (CPS), that divides n successively by every number in the list, starting from the last element in the list. If a zero is encountered in the list, the function should pass 0 to k immediately, without doing any divisions.

dividek 6 [1;3;2] report;;

Result: 1

  • : unit = ()

Answer: let rec dividek n lst k = let rec dividek_aux n list inck = match list with [] -> inck n | 0::xs -> k 0 | x::xs -> dividek_aux n xs (fun r -> inck (r/x)) in dividek_aux n lst k

  1. Assuming Ocaml had callcc and throw implemented as discussed in class (and as implemented in SML/NJ), what would be the result of the following:

a. callcc (fun k -> throw k (10 + 15 + 20 + 25));; Answer: 70

b. callcc (fun k -> throw k (10 + 15) + 20 + 25);;