# Recursion basics

*Summary:* In this laboratory, you will explore some basic concepts in
recursing over lists.

## Preparation

a. Discuss the self check with your partner.

b. Do the normal lab setup. That is

- Start DrRacket.
- Make sure that the
`csc151`

package is up to date. - Add
`(require csc151)`

to the top of the definitions pane.

c. Add the procedures and associated documentation from the corresponding reading to the definitions pane. Be sure to include a short note as to the source of that code.

d. Create a list named `mixed-values`

that contains a dozen or so different
kinds of values. You will likely use an instruction like the following.

```
(define mixed-values
(list 1 'two "three" 4.5 6/7 (list) (list 8) 9+10i ...))
```

## Exercises

### Exercise 1: Testing the `sum`

procedure

a. Read through `sum`

so that you have a sense of how it accomplishes
its purpose.

b. Verify that `sum`

produces the same results as in the corresponding reading.

c. What value do you expect `sum`

to produce for the empty list?

d. Check your answer experimentally.

e. What value do you expect `sum`

to produce for a singleton list? (A “singleton list” is a list with only one value.)

f. Check your answer experimentally.

g. Try `sum`

for a few other lists, too.

h. What do you expect the following to compute?

```
> (sum 1 2 3)
```

i. Check your answer experimentally.

### Exercise 2: Selecting numbers

a. Reread the definition of `select-numbers`

to try to understand what it does.
Then copy the code into your definitions pane.

b. Determine which values in `mixed-values`

are numbers with
`(map number? mixed-values)`

.

c. Create a list of numbers with `(select-numbers mixed-values)`

.

d. Verify that all the resulting values are numbers, using a technique similar to the one that you used in step b.

### Exercise 3: Counting values

Suppose the `length`

procedure, which computes the length of a list,
were not defined. We could define it by recursing through the list,
counting 1 for each value in the list. In some sense, this is much like
the definition of `sum`

, except that we use the value 1 rather than the
value of each element.

a. Using this idea, write a recursive procedure, ```
(list-length
lst)
```

that finds the length of a list. You may not use
`length`

in defining `list-length`

.

b. Check your answer on a few examples: the empty list, the list of values you created, and a few more lists of your choice.

### Exercise 4: Product

Write a recursive procedure, `(product nums)`

, that computes
the product of a list of numbers. You should feel free to use `sum`

as a template for `product`

. However, you should think carefully about
the base case.

### Exercise 5: Counting special values

The `length`

procedure counts the number of values in a list. What if
we don’t want to count every value in a list? For example, suppose we
only want to count the numbers in a mixed list. In this case,
we still recur over the list, but we sometimes count 1 (when the
element is a number) and sometimes count 0 (when it is not).

a. Using this idea, write a procedure, `(tally-numbers lst)`

,
that, given a list, counts how many are numbers. *Note:* You should not
call `list-length`

, `length`

, `filter`

, `tally`

, or `select-numbers`

in
your solution. Instead, use the ideas behind some or all of these
functions in crafting your own recursive solution.

b. Check how your procedure functions on a variety of inputs. For example, you might start with the following

```
> (tally-numbers null)
> (tally-numbers (list 1 2 3))
> (tally-numbers (list "a" "b" "c"))
> (tally-numbers (list 1 "a" 2 "b" 3 "c"))
> (tally-numbers mixed-values)
```

### Exercise 6: The largest element in a list

Using recursion (hence, without `reduce`

or `sort`

or any similar
procedure), write a procedure, `(largest lst)`

, that finds the largest
value in a non-empty list of real numbers. You need not check the
precondition that the list is non-empty nor the precondition that it
contains only reals.

### Exercise 7: A safer `largest`

Rewrite `largest`

using the Husk and Kernel strategy introduced in
the reading on preconditions.

## For those with extra time

The following exercises will challenge you to extend the problem-solving strategies you’ve learned so far.

### Extra 1: Finding skips

(a) Without using `index-of`

, write a procedure, ```
(find-first-skip
lst)
```

that takes a list of symbols as a parameter and returns
the index of the first instance of the symbol `skip`

in * lst*, if skip
appears in lst. Your procedure may return an error if the symbol

`skip`

does not appear in the list.```
> (find-first-skip (list 'hop 'skip 'and 'jump))
1
> (find-first-skip (list 'skip 'hop 'jump 'skip 'and 'skip 'again))
0
> (find-first-skip (list 'hop 'to 'work 'jump 'to 'school 'but 'never 'skip 'class))
8
```

(b) Extend your `find-first-skip`

procedure so that, when the symbol
`skip`

is not in the list, the procedure produces `#f`

rather than
an error.

```
> (find-first-skip (list 'hop 'to 'work 'jump 'to 'school 'but 'never 'skip 'class))
8
> (find-first-skip (list 'hop 'and 'jump))
#f
```

### Extra 2: Finding arbitrary values

Write a procedure, `(my-index-of val lst)`

that takes a
value and a list of values as its parameters and returns the index of
the first instance of * val* in

*, if the value appears in the list. If the value does not appear,*

`lst`

`index-of`

should return `#f`

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

### Extra 3: Riffling lists

Write and document a function `(riffle first second)`

that produces a new list containing alternating elements from the lists * first ... second*. If one list runs out before the other, then the remaining elements should appear at the end of the new list.

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

### Extra 4: Difference

The `sum`

procedure adds up all of the elements in a list. Suppose we
want to compute the difference of the values in the list. For example,
given the list `'(a b c d e)`

, we want `a - b - c - d - e`

.

```
> (difference (list 5))
5
> (difference (list 5 2))
3
> (difference (list 5 2 1))
2
> (difference (list 5 2 1 7))
-5
> (difference (list 5 2 1 7 8))
-13
> (difference (list 5 2 1 7 8 10))
-23
```

a. Come up with a strategy for implementing `difference`

recursively.

b. Implement that strategy.