Assignment 1



Due on Sep 25 before lecture.

Email your solutions to pdarga@umich.edu. Preferably, email them as an attachment, with the filename: your_unique_name.scm



You can download MIT/GNU Scheme from here. Please use Scheme version 7.7.90.

Or, you can log into a CAEN linux machine (such as loginlinux.engin.umich.edu) or a DCO linux machine (such as willow.eecs.umich.edu), and run scheme as follows:
% cd ~bchandra/490
% ./scheme


Problem 1a (1.5 Points)

Recall the function subst we studied in class. (You can also find other scheme examples that we studied in class here.)

Implement a function multisubst. The function multisubst takes three arguments: an atom new, an atom old, and a list of atoms lat. multisubst replaces all occurence of old with new in lat. (Recall that subst replaces only the first occurence of old with new in lat). The following examples illustrate the intended behaviour.

Input Output
(multisubst 'vanilla 'chocolate '()) ()
(multisubst 'vanilla 'chocolate '(vanilla icecream)) (vanilla icecream)
(multisubst 'vanilla 'chocolate '(chocolate icecream)) (vanilla icecream)
(multisubst 'vanilla 'chocolate '(chocolate icecream and chocolate milkshake) (vanilla icecream and vanilla milkshake)
(multisubst 'vanilla 'chocolate '((chocolate) (icecream))) error
(multisubst 'vanilla 'chocolate 'icecream) error



Problem 1b (1.5 Points)

Implement a function subst* that takes three arguments: an atom new, an atom old, and a list l, and replaces all occurence of old with new in l. The following examples illustrate the intended behaviour.

Input Output
(subst* 'vanilla 'chocolate '()) ()
(subst* 'vanilla 'chocolate '(vanilla icecream)) (vanilla icecream)
(subst* 'vanilla 'chocolate '(chocolate icecream)) (vanilla icecream)
(subst* 'vanilla 'chocolate '(chocolate icecream and chocolate milkshake) (vanilla icecream and vanilla milkshake)
(subst* 'vanilla 'chocolate '((chocolate) (icecream))) ((vanilla) (icecream))
(subst* 'vanilla 'chocolate 'icecream) error
(subst* 'orange 'banana '((banana) (split (((banana ice)) (cream (banana)))) (banana brandy))) ((orange) (split (((orange ice)) (cream (orange)))) (orange brandy)))



Problem 2a (0.5 Points)

Write a function sum that takes a list of numbers as its argument and computes the sum of the numbers. You can use the built-in scheme function + to implement sum. The following examples illustrate the intended behaviour.

Input Output
(sum '()) 0
(sum '(1)) 1
(sum '(1 2)) 3
(sum '(1 2 3)) 6
(sum '((1) (2) (3)) error
(sum 1 2 3) error



Problem 2b (0.5 Points)

Write a function product that takes a list of numbers as its argument and computes the product of the numbers. You can use the built-in scheme function * to implement product. The following examples illustrate the intended behaviour.

Input Output
(product '()) 1
(product '(1)) 1
(product '(1 2)) 2
(product '(1 2 3)) 6
(product '(0 1 2)) 0
(product '((1) (2) (3))) error
(product 1 2 3) error



Problem 2c (2 Points)

Notice that the functions sum and product are similar except for a few details. Write a function compute that incorporates the common behavior of sum and product.

(compute + 0) must behave like sum, and (compute * 1) must behave like product. The following examples illustrate the intended behaviour.

Input Output
((compute + 0) '(1 2 3 4)) 10
((compute * 1) '(1 2 3 4)) 24

In general, compute takes two arguments. The first argument is a binary function op. The second argument is the identity element id of that function. The following describes the behavior of compute in the general case.

Input Output
((compute op id) '(s1 s2 s3 ... sk)) Value of the function: (op s1 (op s2 (op s3 ... (op sk id)...)))



Problem 2d (2 Points)

Implement a function mylength using compute that computes the length of a list. The following examples illustrate the intended behaviour.

Input Output
(mylength '()) 0
(mylength '(1)) 1
(mylength '(1 2)) 2
(mylength '(1 2 3)) 3
(mylength '((1) (2) (3))) 3
(mylength '((1) (2) (3 4 5))) 3
(mylength 1 2 3) error



Problem 2e (2 Points)

Implement a function myappend using compute that appends two lists. The following examples illustrate the intended behaviour.

Input Output
(myappend '() '()) ()
(myappend '(1) '()) (1)
(myappend '() '(1)) (1)
(myappend '(1 2 3) '(4 5 6)) (1 2 3 4 5 6)
(myappend '(1 2 3) '((4) 5 6)) (1 2 3 (4) 5 6)



Problem 2f (2 Points)

Implement a function mymap using compute. The function mymap takes two arguments. The first argument is a unary function proc. The second argument is a list l. mymap applies proc element-wise to the elements of l and returns a list of results, in order. The following examples illustrate the intended behaviour.

Input Output
(mymap (lambda (n) (+ n n)) '()) ()
(mymap (lambda (n) (+ n n)) '(1 2 3 4)) (2 4 6 8)
(mymap (lambda (n) (* n n)) '(1 2 3 4)) (1 4 9 16)



Problem 3 (2 Points)

The examples above provide only a minimal set of test cases. Write a comprehensive test suite to test your above implementations. We will use your test suite to test the submissions of all students in the class. You will get more credit if your test cases expose bugs in others' implementations. The goal of this problem is to encourage you to write good test suites.

Write your test cases using the check method, as shown in the following examples. The check method takes two arguments: a test case, and its expected result.

(check '(multisubst 'vanilla 'chocolate '(chocolate icecream)) '(vanilla icecream))
(check '(sum '(1 2 3)) 6)
(check '(mylength '(1 2 3)) 3)

Please only include test cases that test code on valid inputs. That is, if a function expects a list of atoms, please pass only a list of atoms to it. But not, say, an atom, or a list of lists. The point is to make sure the function does the right thing on valid inputs.


[Mail] [bchandra at umich dot edu]