**Question 3:** Define a procedure, `nucleotide-complement`, that takes as input a single base represented by its symbol (`'A`, `'C`, `'T`, or `'G`) and evaluates to the complement of that base.

(define (nucleotide-complement base) (if (eq? base 'A) 'T (if (eq? base 'T) 'A (if (eq? base 'G) 'C (if (eq? base 'C) 'G (error "Bad base: " base))))))

Now that you know the `cond` special form, there is a simpler way:

(define (nucleotide-complement base) (cond ((eq? base 'A) 'T) ((eq? base 'T) 'A) ((eq? base 'G) 'C) ((eq? base 'C) 'G) (else (error "Bad base: " base))))

**Question 4:** Define a procedure, `sequence-complement`, that takes as input a list of symbols representing a DNA sequence, and outputs a list of symbols that are the complement of that sequence.

All we need to do is use `list-map` to apply `nucleotide-complement` to each element in the list:

(define (sequence-complement s) (list-map nucleotide-complement s))

**Question 5:** Define a procedure, `count-matches`, that takes as inputs a list and a value, and outputs the number of elements in the list that match the value. For example, `(count-matches null 'A)` should evaluate to `0` and `(count-matches (list 'A 'C 'A 'T) 'A)` should evaluate to 2. (Note: This is not actually useful for defining Hamming distance, but this question will give you practice with an easier recursive procedure before trying Hamming distance.)

The easiest way is to use `map` to replace all matching elements with `1` and non-matching elements with `0`, and then sum the result:

(define (count-matches p b) (list-sum (map (lambda (v) (if (eq? v b) 1 0)) p)))

**Question 6:** Define a procedure, `hamming-distance`, that takes as inputs two lists and outputs the number of positions where the list elements are different. You may assume that both inputs are the same length (although it would be even better to define a procedure that does not assume this!). Here are some examples: `(hamming-distance null null) ==> 0`, `(hamming-distance (list 'A 'C 'A 'T) (list 'A 'C 'T 'A)) ==> 2`.

We avoid needing to assume the inputs are the same length by counting an element mismatched with a missing element just like any other mismatch. Also note that we can make the procedure shorter and more clear by putting the if expression inside the `+` application expression.

(define (hamming-distance p q) (if (null? p) (length q) (if (null? q) (length p) (+ (if (eq? (car p) (car q)) 0 1) (hamming-distance (cdr p) (cdr q))))))

**Question 8:** Define a procedure, `edit-distance`, that takes as input two lists and outputs the edit distance between those lists.

See Class 10 for more discussion on this.

(define (edit-distance s1 s2) (if (or (null? s1) (null? s2)) (+ (length s1) (length s2)) (min (+ (if (eq? (car s1) (car s2)) 0 1) (edit-distance (cdr s1) (cdr s2))) (+ 1 (edit-distance s1 (cdr s2))) ; insert in s1 (+ 1 (edit-distance (cdr s1) s2)))))) ; delete from s1

**Question 9:** Define a procedure, `memoized-edit-distance`, that computes the edit distance efficiently using memoize to avoid re-computing redundant evaluations.

This is quite tricky. The problem is just replacing all the recursive `edit-distance` calls with `(memoize edit-distance)` doesn't work. The reason is that `(memoize edit-distance)` evaluates to a new procedure. Thus, each place where we apply `(memoize edit-distance)` it produces a new memoized edit-distance procedure, but they do not share the result tables. To support sharing the result tables, we need to create one new procedure that is the result of `(memoize edit-distance)` and use that as the procedure to apply in all the recursive calls.

We do this by making a `generalized-edit-distance` procedure that takes a procedure as input which is the function used in the previously recursive calls.

(define (generalized-edit-distance f s1 s2) (if (or (null? s1) (null? s2)) (+ (length s1) (length s2)) (min (+ (if (eq? (car s1) (car s2)) 0 1) (f (cdr s1) (cdr s2))) (+ 1 (f s1 (cdr s2))) ; insert in s1 (+ 1 (f (cdr s1) s2))))) ; delete from s1 (define memoized-edit-distance (memoize (lambda (s1 s2) (generalized-edit-distance memoized-edit-distance s1 s2))))

You must be logged in to post a comment.