Homework Assignment 11
In this assignment you cannot use any imperative constructs of scheme, such
as set! or the iterative loop constructs. You also are not allowed to use
higher level functions, such as length to get the length of the list. Instead you must
use the basic built-in functions for manipulating a list--car, cdr, cons, append--and
the built-in arithmetic operators to create your functions.
- Write a function in scheme called swap that takes two
arguments and returns a cons pair, with the smaller argument first
and the larger argument second. For example, the call:
(swap 9 6)
should return the cons pair (6 . 9).
- Write a recursive function in scheme named avg
that takes a list of numbers and returns
their average as a floating point number. For example, the call:
(avg '(3 6 17 12 15))
should return 10.6 (and not 53/5 which is what you'll get if you do not
ensure that you have a floating point operand in one of the dividend or
divisor).
- Write a tail-recursive version of the following:
;; find minimum element in a list
(define min
(lambda (l)
(cond
((null? l) '())
((null? (cdr l)) (car l))
(#t (let ((a (car l))
(b (min (cdr l))))
(if (< b a) b a)))))))
- Write a recursive function named mergesort that takes a single list
argument and returns the list in sorted order. For example:
(mergesort '(1 3 2 4 8 1 9 6 10)) ==> '(1 1 2 3 4 6 8 9 10)
As long as you use the purely functional features of scheme (i.e., no
imperative constructs), you may design your merge sort function any way
you see fit. However, it helped me to define the following two helper
functions, which
I created and tested first, and then used them to build mergesort:
- (merge L1 L2): takes two lists and returns a single merged list.
For example,
(merge '(2 4 6) '(1 3 5 9 10)) ==> '(1 2 3 4 5 6 9 10)
- (mergesortHelper L L1 L2 whichlist?): divides a list L into
two separate, equal-sized lists L1 and L2. whichlist? indicates
which list the next element of L should be added to. I used cons
to add the next element of L to either L1 or L2. mergesortHelper
should be recursive and should use continuation-style arguments
for L1 and L2 (i.e., L1 and L2 grow with each successive call
to mergesortHelper). mergesortHelper can either return L1 and L2 as
a cons pair when L is empty, or it can directly implement the
general case of merge sort once L is empty (i.e., call mergesort
on each of the two lists L1 and L2 and call merge to merge the
resulting two lists).
My eventual mergesort was very short. It implemented the two base cases
where the list is either empty or has one element, in which case it
simply returns the list, and it implemented the general case by calling
mergesortHelper with the appropriate initial arguments.
- Write a purely functional Scheme function to return a list containing
all elements of a given list that satisfy a given predicate. For example,
(filter (lambda(x) (< x 5)) '(3 9 5 8 2 4 7))
should return (3 2 4). Your function should be named filter.
- A tree can be defined in Scheme as follows:
- The empty list is an empty tree
- A list with a single element is a tree with a single node (i.e.,
a leaf)
- The first element of a list is the root of the tree. The remaining
elements are sub-trees.
For example the tree:
6
|
-----------
| | |
3 5 8
/ \ |
11 9 ----------
| | | |
1 20 4 17
/ \
7 10
would be represented as the list:
'(6 (3 (11) (9)) (5) (8 (1) (20 (7) (10)) (4) (17)))
Write a function named
fringe that takes a list which represents a tree
and returns a list of
the leaves of the tree, in left-to-right order. For example,
(fringe '(6 (3 (11) (9)) (5) (8 (1) (20 (7) (10)) (4) (17))))
should return
'(11 9 5 1 7 10 4 17)
You must write a recursive definition of
fringe that use the map and fold functions. Look at the
Functional-Languges-Higher-Order-Functions lecture and the
slides
from that lecture if you're not sure what map and fold are. map is
a Scheme built-in function and the Scheme implementation for fold
can be found on the slides.
I would use the map function to apply fringe to the list of sub-trees
for a tree and then use fold to append the lists returned by each invocation
of fringe into a single list.
- In this problem you are going to create a "stream" that lazily generates
fibonacci numbers and you are going to create a function named printFib that
prints the first n elements of this list. To complete this problem, you
need to write two pieces of Scheme code:
- Define a "stream" named fib that lazily creates a list
of fibonacci numbers, assuming that f0 is 0 and f1 is 1. Use the
natural number example from the functional languages evaluation
slides (slide 9) as a
template. Note that you will need to use Scheme's delay
function. Here is a good example of a fib function to modify:
(define fib
(lambda (n)
(letrec ((fib-helper
(lambda (f1 f2 i)
(if (= i n)
f2
(fib-helper f2 (+ f1 f2) (+ i 1))))))
(fib-helper 0 1 0))))
- Define a function named printFib that takes two arguments,
the fib stream object you defined in part a and a number n
that represents the number of fibonacci numbers to print. Print these
fibonacci numbers. For example:
(printFib fib 10) ==> 0 1 1 2 3 5 8 13 21 34
My solution used the display function to print the numbers and
the let construct to ensure that the display functions were executed
in the correct order (i.e., the display function that prints a number
was executed before the display function that printed a space).
My let statement used an empty list for the name-value bindings. Note that
you will need to use Scheme's force function. Again look
at the natural number example as
a template for using the force function. However, your print function
will need to be more sophisticated than the simple tail
function defined in that example.
- Extra Credit (30 points):
Do the online SAIS evaluation for me and any of the TAs
you wish to, and then submit a pdf file with it
as part of your hw 11 submission.
What to Submit
- The functions for all of the questions should be placed in a file
named hw11.scm. We will load this file into the scheme read-eval-print
loop and call your functions with test data to check them.
- Your SAIS confirmation page if you choose to complete it.