- Assigned
- Wednesday, Oct 17, 2018
- Due
- Lab writeups are due at 10:30pm on the day of the next class meeting. For example, a Wednesday lab is due at 10:30pm on Friday. Each lab writeup will be announced at the end of class on a lab day.
- 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.

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))))))
```

We don’t always subtract 1 from `n`

. We might also divide by 2 or make
other changes that get us closer to a target.

```
(define RECURSIVE-PROC
(lambda (n)
(if (zero? n)
BASE-CASE
(COMBINE n (RECURSIVE-PROC (quotient n 2))))))
```

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)
(HELPER STARTING-VALUE 1 n)))
```

We can also use this approach if we are approach `n`

in some way other
than adding one.

```
(define HELPER
(lambda (so-far i n)
(if (> i n)
so-far
(HELPER (UPDATE so-far i) (* i 2) n))))
```

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

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.

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*: You should use `cons`

to build up the list.

*Note*: 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.

Define and test a recursive 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.

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 the `csc151`

package because it is
so useful.)

Implement and test your own version of `iota`

, which you should call
`my-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`

.)

Here is the definition of a procedure that computes the number of digits in
the base-ten representation of the whole portion of `number`

.

```
(define number-of-decimal-digits
(lambda (number)
(if (< number 10)
1
(+ (number-of-decimal-digits (quotient number 10)) 1))))
```

a. Test this procedure.

The definition of `number-of-decimal-digits`

uses direct recursion.

b. Describe the base case of this recursion.

c. Identify and describe the way in which a simpler instance of the problem is created for the recursive call. That is, explain what problem is solved recursively and why you know that that problem is simpler.

d. Explain how the procedure correctly determines that the decimal numeral for the number 2000 contains four digits.

e. What preconditions does `number-of-decimal-digits`

impose on its
argument?

a. Write a procedure, `(powers-of-two n)`

, that produces
a list of all of the powers of two less than or equal to `n`

.

```
> (powers-of-two 5)
'(1 2 4)
> (powers-of-two 10)
'(1 2 4 8)
> (powers-of-two 100)
'(1 2 4 8 16 32 64)
```

b. Write a procedure, `(powers-of-three n)`

, that produces
a list of all of the powers of three less than or equal to `n`

.

```
> (powers-of-three 100)
'(1 3 9 27 81)
> (powers-of-three 1000)
'(1 3 9 27 81 243 729)
```

c. You’ve likely found that `powers-of-two`

and `powers-of-three`

look
remarkably the same. When you find procedures that look the same, one
approach is to write a template. But another is to add an extra parameter.

Write a procedure, `(powers-of k n)`

, that produces a list of all the
powers of `k`

less than or equal to `n`

.

```
> (powers-of 2 100)
'(1 2 4 8 16 32 64)
> (powers-of 3 100)
'(1 3 9 27 81)
> (powers-of pi 100)
'(1 3.141592653589793 9.869604401089358 31.006276680299816 97.40909103400242)
```

d. Rewrite `powers-of-two`

and `powers-of-three`

in terms of `powers-of`

.

*Hint*: Use `section`

.

Using recursion over natural numbers, define a recursive procedure,
`(two-to-the n)`

, that takes a non-negative integer as its input
and returns the result of raising 2 to the power of that number.

For example,

```
> (two-to-the 3)
8
> (two-to-the 0)
1
> (two-to-the 10)
1024
```

It is is possible to implement the procedure non-recursively, using
Scheme’s primitive `expt`

procedure. The point of this exercise is
to use recursion.

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).*

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

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

`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 `take`

, you should not
call `take`

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

The typical definition of `two-to-the`

looks something like the
following.

```
(define two-to-the
(lambda (n)
(if (zero? n)
1
(* 2 (two-to-the (- n 1))))))
```

This definition requires approximately `n`

recursive calls. Can we
do better? It turns out we can, if we take advantage of a simple rule
about exponentiation: 2 to the 2*k power is the same as the square
of 2 to the kth power. 2^2k = 2^k*2^k.

Using that technique for even powers, come up with a more efficient
version of `two-to-the`

.

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

`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))))))
```

We begin by considering the base case. The last example may give 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

`n`

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

Putting it all together, we get

```
;;; Procedure:
;;; value-replicate
;;; Parameters:
;;; n, a non-negative integer
;;; val, a Scheme value
;;; 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 (n val)
(if (zero? n)
null
(cons val (value-replicate (- n 1) val)))))
```