Professional Documents
Culture Documents
Name:__________________________________________________________________
Student Number:_________________________________________________________
INSTRUCTIONS:
2. Exam questions will not be explained, and no hints will be given. If you think something
is unclear or ambiguous, make a reasonable assumption (one that does not contradict the
question), write it at the start of your solution, and answer the question.
3. The last page of this question paper is blank. You can use that page for rough work.
Nothing written on that page will be marked.
4. The crib sheet at the end of this question paper summarizes some Racket procedures that
you may find useful. You are free to use procedures that aren't listed on the sheet;
however, procedures other than the ones listed there aren't required for any of the
solutions.
5. All pages of this question paper, including the crib sheet and the rough-work page, must
be turned in.
Question 1 _____________/ 3
Question 2 _____________/ 4
Question 3 _____________/ 5
Question 4 _____________/ 5
Question 5 _____________/ 10
Question 6 _____________/ 3
Total __________________/ 30
1
Question 1 [3 marks]
Every powerful programming language provides three mechanisms for combining simple ideas
to form more complex ideas:
● primitive expressions, which represent the simplest building blocks that the language
provides,
● means of combination, by which compound elements are built from simpler ones, and
● means of abstraction, by which compound elements can be named and manipulated as
units.
Racket associates pi with a value that approximates the mathematical constant 𝜋.
(a) List one primitive expression in this define special form. (1 mark)
Solution:
● 10 is a primitive expression (a number)
● * is a primitive expression (primitive procedure)
(b) List one means of combination in the define special form. (1 mark)
Solution:
● (* pi 10 10) A list of expressions forms a compound expression. In this example, the
compound expression represents the application of procedure * to the arguments (the
values of pi and 10)
● * is not a means of combination in a language where expressions are written using prefix
notation.
(c) List one means of abstraction in the define special form. (1 mark)
Solution:
● area (the name associated with the expression (* pi 10 10)). define area was
also acceptable.
● pi (the name associated with the number that represents the the mathematical constant 𝜋)
2
Question 2 [4 marks]
On the ruled lines, write the values that Racket displays after it evaluates each expression. If an
expression returns a procedure, write "Procedure". If Racket displays an error message, write
"Error". If nothing is displayed, write "Nothing".
Solution: Racket displays: '((5 10) 15 20) No marks were deducted if the only error was
omitting the leading quote, because some Scheme REPLs omit it.
I also accepted (list (list 5 10) 15 20), even though this is not what Racket displays,
because it is equivalent to: '((5 10) 15 20)
Explanation: The expression (cons (list 5 10) (list 15 20)) is equivalent to:
We are creating a new list. Recall that Racket lists are implemented as linked lists of pairs.
● The first part of the first pair points to the list '(5 10). The second part of the first pair
points to the second pair.
● The first part of the second pair points to 15, and the second part of the second pair
points to the third pair.
● The first part of the third pair points to 20, and the second part of the third pair is the
empty list.
Common Error: Racket doesn't display '(5 10 15 20). This is a list of 4 integers. Two
cons expressions that produces this list are:
To create this list from the two lists, (list 5 10) and (list 15 20), we use append, not
cons:
Common Error: Racket doesn't display '((5 10) (15 20)). This is a list of two lists. A
cons expression that produces this list is:
3
> (cdr (car '((1 2) (3 4))))
Solution: Racket displays '(2) No marks were deducted if the only error was omitting the
leading quote.
Explanation:
(car '((1 2) (3 4))) yields the list '(1 2), and (cdr '(1 2)) yields the list '(2)
Common Error: Many students correctly deduced that the cdr/car expression would select the
second element, 2, from the first list '(1 2), but stated that Racket would display 2. It doesn't:
cdr always returns a list.
Solution: Racket displays 15. (adder-1 5) returns a lambda procedure in which x is bound to
5. When this procedure is called with argument 10, the body of the lambda evaluates to (+ 5
10), which is 15.
Solution: Racket displays 30. (adder-2 5) returns a lambda procedure that has two formal
parameters, x and y. When this procedure is called with arguments 10 and 20 the body of the
lambda evaluates to (+ 10 20), which is 30. (The 5 bound to adder-2's formal parameter x
isn't used in the lambda.)
4
Question 3 [5 marks]
Use the substitution model to illustrate the process generated by this procedure application:
(mystery 3 1) ; (3 marks)
Solution:
(mystery 3 1)
==> (mystery (- 3 1) (+ 1 3)) ; subst. args into formal params
; n and csum
==> (mystery 2 4) ; evaluate subexpressions & apply mystery
==> (mystery (- 2 1) (+ 4 2)) ; subst. args into formal params
; n and csum
==> (mystery 1 6) ; evaluate subexpressions & apply mystery
==> (mystery (- 1 1) (+ 6 1)) ; subst. args into formal params
; n and csum
==> (mystery 0 7) ; evaluate subexpressions & apply mystery
==> 7
Common Error: most students who applied the substitution model incorrectly used the wrong
value of n when evaluating (+ csum n). Often, these students skipped over steps; e.g.,
combining the argument substitution step with the next recursive call, and lost track of the values
of the arguments.
Is this process recursive or iterative? (1 mark) Briefly explain your answer. (1 mark)
Solution: the process is iterative. (The procedure is recursive, but the process it generates is
iterative.)
Notice that mystery produces csum + n + n-1 + … + 2 + 1. The accumulating sum is
the procedure's second argument.
I accepted any explanation that showed that you understand that an iterative procedure will
execute in constant space (e.g., no expansion followed by contraction in the chain of procedure
calls, the addition operation isn't deferred until mystery returns, etc.)
5
Question 4 [5 marks]
Assume you have been provided with procedure (power x n) that calculates xn, n ≥ 0.
Define a recursive procedure sum-powers that takes two arguments, a number x and an integer
n, n ≥ 1. The procedure calculates x + 2x2 + 3x3 + ... + n · xn by means of a recursive process.
Your sum-powers procedure must use the power procedure. Do not define power.
Solution:
The formulae for the two cases this procedure must handle are:
f (x, n) = n · xn + (n − 1) xn−1 + ... + 3x3 + 2x2 + n = n · xn + f (x, n − 1), when n > 1 (recursive case)
(define (sum-powers x n)
(if (= n 1)
x
(+ (* n (power x n))
(sum-powers x (- n 1)))))
No marks were deducted for using this base case: (if (= n 0) 0 … ), even though this
results in an extra recursive call to sum-powers.
Some students defined a recursive inner helper procedure that was called by sum-powers. No
marks were deducted if the resulting process was recursive; however, make sure you understand
why a helper procedure isn't needed. Sometimes, the helper implemented an iterative process,
which was incorrect, as the question specified that the procedure generate a recursive process.
It was not necessary for your procedure to type-check or range-check the values bound to the
parameters; e.g., check if x is a number and n is a positive integer.
6
Question 5 [10 marks]
(a) (5 marks) Define a recursive procedure count-multiples that takes two arguments, a list
of integers and an integer n, n ≥ 1. The procedure counts the number of elements in the list that
are a multiple of n, by means of a recursive process. For example,
2. If the first element in a list is a multiple of n, the number of multiples equals 1 plus the
number of multiples in the rest of the list (recursive case).
3. If the first element in a list is not a multiple of n, the number of multiples equals the
number of multiples in the rest of the list (recursive case).
This is clearly a recursive process, because the addition is deferred until count-multiple
returns.
7
(b) (5 marks) Rewrite your solution to part (a) as procedure that generates an iterative process.
Solution: We need a recursive helper process that has three parameters: the list, n, and an
accumulating count of the number of elements that are multiples of n. The procedure executes in
constant space (result contains the correct count of multiples when the base case is reached),
so the process is iterative.
Common errors:
1. The base case returns 0 instead of the accumulated result; e.g., ((empty ? lst) 0)
2. The expression for the third argument passed to helper is incorrect; i.e., using result
when (+ result 1) is required, or vice-versa.
8
Question 6 [3 marks]
Racket provides a procedure (list-ref lst pos), which takes a list, lst, and a
non-negative position, pos. It returns the list element at position pos. The list's first element is at
position 0. For example,
Define a procedure ordinal that takes a non-negative integer argument n. It returns a procedure
that takes one argument, a list, and returns the n'th element in the list, counting from one (1). For
example:
Solution:
(define (ordinal n)
(lambda (lst) (list-ref lst (- n 1))))
Notice that list-ref's second argument is (- n 1), not n, because ordinal counts from 1,
but list-ref considers 0 to be the position of the first element in the list.
Common errors:
● ordinal calls the lambda (or calls list-ref) instead of returning a procedure;
● the procedure returned by ordinal has two formal parameters (e.g., a list and a
position).
9
Crib Sheet
Numbers
+, -, *, / are the addition, subtraction, multiplication and division operators.
=, <, <=, >, >= are the numeric comparison operators, and return #t or #f.
(quotient n m) returns the integer result when integer n is divided by integer m.
(remainder n m) returns the integer remainder when integer n is divided by integer m. The
remainder has the same sign as n.
(null? v) returns #t if v is the empty list, #f otherwise.
(list? v) returns #t if v is a list; that is, if v is the empty list or a pair whose second element
is a list.
(cons a b) returns a newly allocated pair whose first element is a and second element is b.
(append lst1 lst2 … lstn) returns a list containing all the elements of the given lists in
order. All lists except the last one are copied, but lstn is appended, not copied.
(member v lst) locates the first element in lst that is equal? to v. If that element exists,
the tail of lst starting with that element is returned. Otherwise, #f is returned.
10