# Laboratory: Numeric Recursion

*Summary:* Although most of our prior experiments with recursion have emphasized recursion over lists, it is also possible to use other values as the basis of recursion. In this laboratory, you will explore the use of natural numbers (non-negative integers) as the basis of recursion.

## Reference

Here is a template for the simplest kind of numeric recursive procedures.

```
(define recursive-proc
(lambda (n)
(if (zero? n)
base-case
(combine n (recursive-proc (- n 1))))))
```

You can also use helper recursion to achieve a variety of other goals. For example, helper recursion can let you count up from 1 to * n*. (A slight change to the following code will allow you to count up from 0 to

*.)*

`n`

```
(define helper
(lambda (so-far i n)
(if (> i n)
so-far
(helper (update so-far i) (+ i 1) n))))
(define primary
(lambda (n)
(kernel starting-value 1 n)))
```

## Preparation

Make a copy of ** numeric-recursion-lab.rkt**, which contains important code from the reading.

## Exercises

### Exercise 1: Counting Down

Define and test a *recursive* Scheme procedure, `(count-down val)`

, that takes a natural number as argument and returns a list of all the natural numbers less than or equal to that number, in descending order.

```
> (count-down 5)
'(5 4 3 2 1 0)
> (count-down 0)
'(0)
```

Note that you should use `cons`

to build up the list.

Note also that you are better off writing this with direct recursion (the first pattern above), rather than using a helper procedure.

When you are finished, you may want to read the notes on this exercise.

### Exercise 2: Filling Lists

Define and test a Scheme procedure, `(value-replicate count value)`

, that takes two arguments, the first of which is a natural number, and returns a list consisting of the specified number of repetitions of the second argument.

```
> (value-replicate 5 "sample")
'("sample" "sample" "sample" "sample" "sample")
> (value-replicate 3 10)
'(10 10 10)
> (value-replicate 1 null)
'(())
> (value-replicate 2 null)
'(() ())
> (value-replicate 0 "hello")
'()
```

You should not call the built-in `make-list`

procedure. Instead, implement `value-replicate`

recursively.

When you are finished writing this procedure, compare it to the notes on this exercise.

### Exercise 3: Counting To

As you may recall, `iota`

is a procedure that takes a natural number as argument and returns a list of all the natural numbers that are strictly less than the argument, in ascending order. As you’ve seen, the `iota`

procedure is quite useful. Unfortunately, it does not come as part of standard Scheme. (We include it in MediaScheme because it is so useful.)

Implement and test your own version of `iota`

. (You should not call the MediaScheme `iota`

.)

For example,

```
> (my-iota 3)
'(0 1 2)
> (my-iota 5)
'(0 1 2 3 4)
> (my-iota 1)
'(0)
```

Note that you will probably need to use a helper of some sort to write `my-iota`

. You might use the traditional form of helper, which adds an extra parameter. You might also use a helper that simply computes the list in the reverse order. (Most students write a backwards version in the first attempt; instead of throwing it away, rename it and call it from `my-iota`

.)

### Exercise 4: Counting Between

You may recall the `count-from`

procedure from the reading on recursion over natural numbers, which is available in the code for this lab.

a. What is the value of the call `(count-from -10 10)`

?

b. Check your answer experimentally.

c. It is possible to implement `count-from`

in terms of `iota`

. The implementation looks something like the following.

```
(define count-from
(lambda (lower upper)
(map (l-s + _____) (iota _____))))
```

Finish this definition.

d. What do you see as the advantages and disadvantages of each way of defining `count-from`

?

## For Those Who Finish Early

### Extra 1: The Nth Element

Write a procedure, `(my-list-ref lst n)`

, that extracts element * n* of a list. For example,

```
> (my-list-ref (list "red" "orange" "yellow" "green" "blue" "indigo" "violet") 5)
"indigo"
> (my-list-ref (list "red" "orange" "yellow" "green" "blue" "indigo" "violet") 0)
"red"
```

Even though this procedure does the same thing as `list-ref`

, you should not use `list-ref`

to implement it. Instead, your goal is to figure out how `list-ref`

works, which means that you will need to implement this procedure using direct recursion.

*Hint: When recursing, you will need to simplify the numeric parameter (probably by subtracting 1) and the list parameter (probably by taking its cdr).*

### Extra 2: Computing List Prefixes

Define and test a recursive procedure, `(list-prefix lst n)`

, that returns a list consisting of the first * n* elements of the list,

*, in their original order. You might also think of*

`lst`

`list-prefix`

as returning all the values that appear before index *.*

`n`

For example,

```
> (list-prefix (list "a" "b" "c" "d" "e") 3)
("a" "b" "c")
> (list-prefix (list 2 3 5 7 9 11 13 17) 2)
(2 3)
> (list-prefix (list "here" "are" "some" "words") 0)
()
> (list-prefix (list null null) 2)
(() ())
> (map rgb->color-name (list-prefix (map color-name->rgb (list "black" "white" "green") 1))
("black")
```

While your procedure has much the same purpose as `list-take`

, you should not call `list-take`

. Rather, your goal is to implement the procedure recursively.

## Notes

### Notes on Exercise 1: Counting Down

Here’s a possible solution to the problem. The base case is easy. If the number is zero, then the list of all non-negative numbers less than or equal to zero is the list that contains only zero.

```
(if (zero? n)
(list 0)
```

In the recursive case, we assume that we can compute the list of all numbers less than or equal to * n*-1. To get the complete list, we simply add

*to the front.*

`n`

```
(cons n (count-down (- n 1)))
```

Putting it all together, we get

```
;;; Procedure:
;;; count-down
;;; Parameters:
;;; n, a non-negative integer
;;; Purpose:
;;; Create a list of the form (n n-1 n-2 ... 3 2 1 0).
;;; Produces:
;;; nums, a list
;;; Preconditions:
;;; [No additional.]
;;; Postconditions:
;;; (length nums) = n+1
;;; (list-ref nums i) = n-i for all i, 0 <= i <= n.
(define count-down
(lambda (n)
(if (zero? n)
(list 0)
(cons n (count-down (- n 1))))))
```

### Notes on Exercise 2: Filling Lists

We begin by considering the base case. The last example gives a hint: If you want zero copies, you end up with the empty list.

```
(if (zero? n)
null
```

Now, on to the recursive case. If we can create a list of * n*-1 copies, we can then create a list of

*copies by prepending one more copy.*

`n`

```
(cons val (value-replicate val (- n 1)))
```

Putting it all together, we get

```
;;; Procedure:
;;; value-replicate
;;; Parameters:
;;; val, a Scheme value
;;; n, a non-negative integer
;;; Purpose:
;;; Create a list of n copies of val.
;;; Produces:
;;; val-lst
;;; Preconditions:
;;; [No additional]
;;; Postconditions:
;;; (length val-lst) is n
;;; (list-ref val-list i) is val for all i, 0 <= i < n
(define value-replicate
(lambda (val n)
(if (zero? n)
null
(cons val (value-replicate val (- n 1))))))
```