- Assigned
- Wednesday, 3 April 2019
- Due
- Tuesday, 9 April 2019 by 10:30pm
- Summary
- For this assignment, you will apply your knowledge of recursion to solve a variety of problems that require different kinds of general repetition.
- Collaboration
- You must work with your assigned partner(s) on this assignment. You may discuss this assignment with anyone, provided you credit such discussions when you submit the assignment.
- Submitting
- Email your answers to csc151-01-grader@grinnell.edu. The subject of your email should be
**[CSC151 01] Assignment 7**and should contain your answers to all parts of the assignment. Please send your scheme code in an attached`.rkt`

file.

*Topics:* code reading, recursion

One way to really understand what is happening in a recursive procedure is
to trace the steps as Scheme evaluates the portions of the procedure in its
traditional “inside-out” form. For example, given the non-helper version of
`sum`

, we might write the following trace.

```
(sum (list 38 12 83))
; Not null
=> (+ (car (list 38 12 83) (sum (cdr (list 38 12 83)))
; Simplify car/cdr
=> (+ 38 (sum (list 12 83)))
; Not null
=> (+ 38 (+ (car (list 12 83)) (sum (cdr (list 12 83)))))
; Simplify car/cdr
=> (+ 38 (+ 12 (sum (list 83))))
; Not null
=> (+ 38 (+ 12 (+ (car (list 83)) (sum (cdr (list 83)))))))
; Simplify car/cdr
=> (+ 38 (+ 12 (+ 83 (sum null))))
; Null case
=> (+ 38 (+ 12 (+ 83 0)))
; Evaluate innermost expression
=> (+ 38 (+ 12 83))
; Evaluate innermost expression
=> (+ 38 95)
; Evaluate innermost expression
=> 133
```

Consider the two following versions of `tally-odd`

.

```
;;; Procedure:
;;; tally-odd
;;; Parameters:
;;; nums, a list of integers
;;; Purpose:
;;; Count how many values in nums are odd
;;; Produces:
;;; number-odd, a count of how many values are odd.
(define tally-odd-a
(lambda (nums)
(cond
[(null? nums)
0]
[(not (integer? (car nums)))
(error "tally-odd expects a list of integers. Your list contains "
(car nums))]
[(odd? (car nums))
(+ 1 (tally-odd-a (cdr nums)))]
[else
(tally-odd-a (cdr nums))])))
(define tally-odd-b
(lambda (nums)
(tally-odd-b-kernel nums 0)))
(define tally-odd-b-kernel
(lambda (remaining tally-so-far)
(cond
[(null? remaining)
tally-so-far]
[(not (integer? (car remaining)))
(error "tally-odd expects a list of integers. Your list contains "
(car remaining))]
[(odd? (car remaining))
(tally-odd-b-kernel (cdr remaining) (+ 1 tally-so-far))]
[else
(tally-odd-b-kernel (cdr remaining) tally-so-far)])))
```

Write traces of the evaluation of `tally-odd-a`

and `tally-odd-b`

(and
`tally-odd-b-kernel`

, since that’s where the real work happens) on the
input `'(5 2 7 3 6)`

.

```
(tally-odd-a '(5 2 7 3 6))
; Not empty, car is odd
=> (+ 1 (tally-odd-a (cdr '(5 2 7 3 6))))
...
(tally-odd-b '(5 2 7 3 6))
=> (kernel '(5 2 7 3 6) 0)
; Not empty, car is odd
=> (kernel (cdr '(5 2 7 3 6)) (+ 1 0))
...
```

*Topics:* recursion, conditionals

Document and write a recursive procedure, `(contains? lst val)`

,
that returns true (`#t`

) if `val`

appears in `lst`

and `false`

otherwise.

```
> (contains? (list 'a 'b 'c) 'a)
#t
> (contains? (list 'a 'b 'c) 'b)
#t
> (contains? (list 'a 'b 'c) 'c)
#t
> (contains? (list 'a 'b 'c) 'd)
#f
```

*Topics:* list recursion

As you know, the `(index-of lst val)`

procedure finds the
index of the *first* instance of `val`

in `lst`

. If `val`

is not in `lst`

,
it returns the value `#f`

.

Suppose `index-of`

did not exist. We could write it ourselves.

Document and write a recursive procedure, ```
(my-index-of lst
val)
```

, that provides the first index of `val`

within
`lst`

. If the value does not appear, `my-index-of`

should return `#f`

.

```
> (my-index-of (list 'hop 'skip 'and 'jump) 'skip)
1
> (my-index-of (list 5 4 3 2 1 2 3 4 5) 5)
0
> (my-index-of (list "pencils" "paper" "index cards" "markers" "ball-point pens") "eraser")
#f
```

*Note*: You may not use `list-ref`

(or `index-of`

) in implementing `my-index-of`

.

*Topics:* list recursion

As you know, the `(index-of lst val)`

procedure finds the
index of the *first* instance of `val`

in `lst`

. If `val`

is not in `lst`

,
it returns the value `#f`

.

What if we wanted *all* of the indices, not just the first one? We’d
probably have to write our own procedure.

Document and write a recursive procedure, ```
(indices-of val
lst)
```

, that creates a list of all the position in `lst`

where `val`

appears. If the value does not appear, `indices-of`

should
return the empty list.

```
> (indices-of 'skip (list 'hop 'skip 'and 'jump))
'(1)
> (indices-of 'skip (list 'hop 'skip 'jump 'and 'skip 'again))
'(1 4)
> (indices-of 5 (list 5 4 3 2 1 2 3 4 5))
'(0 8)
> (indices-of "eraser" (list "pencils" "paper" "index cards" "markers" "ball-point pens"))
'()
```

Note: You may not use `list-ref`

(or `index-of`

) in implementing `indices-of`

.

*Topics:* list recursion

Document and write a procedure, `(riffle2 first second)`

, that
produces a new list containing alternating elements from the lists
`first`

and `second`

. If one list runs out before the other, then the
remaining elements should appear at the end of the new list.

```
> (riffle2 (list 'a 'b 'c) (list 'x 'y 'z))
'(a x b y c z)
> (riffle2 (list 'a 'b 'c) (iota 10))
'(a 0 b 1 c 2 3 4 5 6 7 8 9)
> (riffle2 (iota 10) (list 'a 'b 'c)
'(0 a 1 b 2 c 3 4 5 6 7 8 9)
> (riffle2 null (list 'a 'b 'c))
'(a b c)
```

*Note*: There’s a clever approach that involves looking only at the
first list (but changing which list is first). You need not undertake
this approach, but you should spend a minute or two thinking about it.

*Topics:* list recursion

Document and write a procedure, `(riffle3 first second third)`

,
that produces a new list containing alternating elements from the lists
`first`

, `second`

, and third. If one list runs out before the others,
continue riffling the remaining two lists.

```
> (riffle3 (list 'a 'b 'c) (list 'p 'q 'r) (list 'x 'y 'z))
'(a p x b q y c r z)
> (riffle3 (list 'a 'b 'c 'd) (list 'e 'f) (list 'g 'h 'i))
'(a e g b f h c i d)
> (riffle3 (list 'a 'b 'c) null (list 'd 'e 'f))
'(a d b e c f)
> (riffle3 (list 'c 'b 'a) (list 'd 'd 'd) (list 'e 'f 'g))
'(c d e b d f a d g)
```

*Note*: You are permitted to use `riffle2`

when you run out of
elements in one of the lists.

*Topics:* list recursion, sorting

Write but do not document a recursive procedure, ```
(merge-sorted-lists
lst1 lst2)
```

, that takes as input two lists of strings
that are each ordered alphabetically and returns the combination
of those two lists, still in alphabetical order

You may *not* use `sort`

in your solution.

```
> (merge-sorted-lists '("alpha" "gamma" "yak" "zebra")
'("bracket" "cheese" "hello" "world" "zap"))
'("alpha" "bracket" "cheese" "gamma" "hello" "world" "zap" "zebra")
> (merge-sorted-lists '("alpha" "delta" "echo" "foxtrot" "xerxes")
'("alpha" "delta" "gamma" "xerxes"))
'("alpha" "alpha" "delta" "delta" "echo" "foxtrot" "gamma" "xerxes" "xerxes")
```

*Note*: The input lists must be in alphabetical order. You need not
handle inputs not in alphabetical order.

*Topics:* lists, recursion, sorting

Write a procedure, `(alphabetical-order? words)`

, that takes a list
of strings as input and returns true if the words are in alphabetical
order (aka ASCII order) and false otherwise. You may assume that
all of the elements in the list are strings.

```
> (alphabetical-order? '("alpha" "beta" "delta" "epsilon"))
#t
> (alphabetical-order? '("alpha" "beta" "gamma" "delta" "epsilon"))
#f
> (alphabetical-order? '())
#t
```

We will primarily evaluate your work on *correctness* (does your code
compute what it’s supposed to and are your procedure descriptions
accurate); *clarity* (is it easy to tell what your code does and how
it achieves its results; is your writing clear and free of jargon);
and *concision* (have you kept your work short and clean, rather than
long and rambly).