Wizard

COMP 524: Programming Language Concepts

Spring, 2008
Jeff Terrell
jsterrel AT cs.unc.edu
(919) 962-1791 (office: Sitterson 138)

COMP 524 Exercise 2 (Scheme)

General Instructions

First, review the assignment submission policy in the syllabus. Note that there is no collaboration allowed.

This assignment is due at 11:59pm on Friday, March 7. Submit assignments to me via email. All of your functions should be included in a file called 'exercise2.scm', and 'exercise2.scm' should include everything that you turn in. When I am finished grading your assignment, I will email you your grade and any comments that I have (assuming I have your permission for this). There are a total of 100 points.

Remember: start early! I guarantee my availability during office hours, but not at 11pm the night it is due.

When you turn in exercise2.scm, there should be no statements at the top level that produce output or require input. Merely provide the required functions and anything the functions need--do not include any code related to your testing or debugging. When I import your functions into another script, I want the import to be silently successful. Thank you.

My solutions are available.

1. Chasing the Tail

Details
Define a procedure last-pair that returns the list that contains only the last element of a given (nonempty) list.
Example
(last-pair (list 23 72 149 34))
(34)
Points
10 points
Par
2 minutes

2. Reversing Lists

Details
Define a procedure reverse that takes a list as the argument and returns a list of the same elements in reverse order.
Example
(reverse (list 1 4 9 16 25))
(25 16 9 4 1)
Hint
If you're using the Gambit Scheme Interpreter (gsi), you may want to use the pretty-print function with lists. (It's more legible than the print function.)
Points
10 points
Par
12 minutes

3. Dotted Tails

Summary
Practice using dotted-tail notation to define variable-argument procedures.
Background

The procedures +, *, and list take arbitrary numbers of arguments. One way to define such procedures is to use define with dotted-tail notation. In a procedure definition, a parameter list that has a dot before the last parameter name indicates that, when the procedure is called, the initial parameters (if any) will have as values the initial arguments, as usual, but the final parameter's value will be a list of any remaining arguments.

For instance, given the definition (define (f x y . z) <body>), the procedure f can be called with two or more arguments. If we evaluate (f 1 2 3 4 5 6), then, in the body of f, x will be 1, y will be 2, and z will be the list (3 4 5 6). As another example, given the definition (define (g . w) <body>), the procedure g can be called with zero or more arguments. If we evaluate (g 1 2 3 4 5 6), then, in the body of g, w will be the list (1 2 3 4 5 6).

Details
Use this notation to write a procedure same-parity that takes one or more integers and returns a list of all the arguments that have the same even-odd parity as the first argument.
Examples

Update 2008-02-26, 11:20am: the examples were wrong. The first argument should not be part of the list that is returned. So (same-parity 1 3) returns (3), not (1 3). (This makes it easier to write this function. If you already have a function which works the old way, you can just use that; I will accept it either way.)

(same-parity 3 1 2 3 4 5 6 7)
(1 3 5 7)
(same-parity 2 2 3 4 5 6 7)
(2 4 6)
Hints

One problem is how to call a variable-argument function with a list, so that the arguments are in the list. To do this, use the apply function. For example, (+ (list 1 2)) gives Error: number expected, but (apply + (list 1 2)) gives 3.

You might want to use the modulo or odd? functions provided with Scheme.

Points
10 points
Par
11 minutes

4. Products

Summary
Write an abstract function for product forms.
Background
The sum procedure that we saw in class is only the simplest of a vast number of similar abstractions that can be captured as higher-order procedures. Recall that sum looked like this:
(define (sum term a next b)
  (if (> a b)
      0
      (+ (term a)
         (sum term (next a) next b)
      )
  ))
Details

Write an analogous procedure called product that returns the product of the values of a function at points over a given range. Define a function factorial in terms of product. Also use product to compute approximations to pi using the formula:

Approximation to PI/4

by defining a function pi-approx that accepts a single argument n, the number of terms to use in the approximation (where 2/3 is one term, 4/3 is another, and so on).

Then, make product into a tail-recursive procedure called prod-iterative.

Examples
(factorial 5)
120
(pi-approx 5)
2.9257142857142853
(pi-approx 10000)
3.1417497057379746
Hint
To keep Scheme from representing numbers as fractions, specify a number literal with a decimal point. (/ 2 8) is 1/4, but (/ 2. 8) is .25.
Points
5 for product; 5 for prod-iterative; 5 for factorial; and 5 for pi-approx.
Par
33 minutes

5. Pascal's Triangle

Summary
Compute a row of Pascal's Triangle.
Background
The following pattern of numbers is called Pascal's Triangle:
    1
   1 1
  1 2 1
 1 3 3 1
1 4 6 4 1
That is, each number is the sum of the numbers immediately above it, with 1's along the outside.
Details
Write a Scheme function called pascal-row that returns a list of the i-th row of Pascal's Triangle.
Examples
(pascal-row 1)
(1 1)
(pascal-row 17)
(1 17 136 680 2380 6188 12376 19448 24310 24310 19448 12376 6188 2380 680 136 17 1)
Points
20 points
Par
10 minutes

6. Simpson's Rule

Summary
Apply Simpson's rule to numerically compute integral approximations.
Background

Simpson's Rule is an accurate method of numerical integration. Using Simpson's Rule, the integral of a function f between a and b is approximated as:

Equation for Simpson's Rule

where h = (b - a)/n, for some even integer n, and yk = f(a + kh). (Increasing n increases the accuracy of the approximation.)

Details

Define a procedure that takes as arguments f, a, b, and n and returns the value of the integral, computed using Simpson's Rule. Call your procedure simpson.

Then, write a procedure that integrates cube (i.e. (lambda (x) (* x x x))) from 0 to 1 and only accepts n as an argument. Your procedure should call simpson to perform the integration. Call this procedure approx-int-cube.

Note: when using Gambit Scheme, I ran into a problem if I made n too large. Apparently, the + operator cannot handle more than 8,191 arguments. So, I will not grade your problem with n larger than 8,000. (Remember that n is supposed to be even.)

Example
(simpson sin 0. 3.1415926 1000)
2.0000000000010814
(approx-int-cube 10)
.25
(approx-int-cube 100)
.25000000000000006
(approx-int-cube 1000)
.25
(approx-int-cube 8190)
.25000000000000033
Hint
You might find the let* special form to be helpful here. It's like let, except that the scope of each variable is extended to include all following declarations. The effect is that you can effectively chain defines.
Points
25 points for simpson; 5 for approx-int-cube
Par
46 minutes, +20 more debugging after I learned that my answers were off.
exercise2.php: Last Modified: 04/01/08@17:38:05 | Size: 10332 bytes | View Source Valid XHTML 1.1 Valid CSS