## Flowcharts and recursion

When circumstances allow, I'll be typing up bits of my lecture notes and posting them online. These may or may not bear any resemblance to the actual lectures.

### Chapter 6

Chapter 6 is about organizing and designing computer programs. If you don't have a clear idea of how your program is supposed to work, it's likely it won't. Reading Chapter 6 is one way to prepare for your midterm project.

In class we'll cover only flowcharts, which describe the "flow of control" in a computer program. Using a flowchart, you can diagram what choices the computer has at each decision point (if or ifelse statement). A flowchart can include as much or as little detail as you need.

Below is an example of a simple flowchart describing the process of waking up in the morning:

Notice that actions are described in rectangular boxes, decisions appear in diamond shaped boxes, and the start and end are in circles. Arrows indicate the "flow of control" in the program. (I don't know what the green bullet shape is for.) We'll display events in which the computer reads or displays something in parallelogram shaped boxes, as you can see from this flow chart describing a familiar quiz program.

#### Maze Game

Here is a flow chart describing a maze game. Save your work, then write a maze game that prints the responses shown in the parallelograms of the flow chart and makes decisions as described in the diamonds.
• What helper procedures do you use?
• Can your game get stuck in an "infinite loop"? Why or why not?

### Chapter 7

Since early in the semester we've had in mind the question of how to separate a list into two lists -- what's the opposite of sentence? To do this, we need a way to repeat an operation for certain items in the list (e.g. adding them to a new list). We just saw an example of a maze game which asks a question repeatedly until a certain condition is met -- this could help us work with lists! Chapter 5 also has some tools that will be useful for this.

When a procedure is used as its own helper procedure in a program, we call that program recursive. Recursive programs are often the best way to apply functional programming techniques to a problem.

Recall our example of using Newton's Method to find the zeros of a function. Let's use it to estimate ln(4) by finding the value of x for which ex - 4 = 0.

```to function :value
output (exp :value) - 4
end

to derivative :value
output exp :value
end

to improve_guess :guess
output :guess - (function :guess) / (derivative :guess)
end
```
Once we've copied and pasted this little program into Logo, we can estimate ln(4) as follows:
```? print improve_guess 2
1.54134113294645
? print improve_guess 1.5
1.39252064059372
? print improve_guess 1.4
1.38638785576643
? print improve_guess 1.386387
1.38629436541074
```
The values output by Logo have mostly stopped changing, so this answer is probably right. We can test it by plugging it in to procedure function and seeing if we get 0.
```? print function 1.38629
-1.74444415237396e-005
?
```
Yup, looks good!

That was annoying. The work of calculating the function and its derivative can't be avoided, but Logo should be able to repeat procedure improve_guess without our having to type it in a bunch of times.

Instead of typing improve_guess at the keyboard a large number of times we will use if and recursion to stop the procedure when our guess is improved to the desired accuracy. We'll do this by making changes to the improve_guess procedure to make it keep working until the guess is good enough.

How do we want to change improve_guess?

• How do we know when the guess is good enough?
• How will we use Logo to check for that?
• Where in the procedure should we do that check?
• What should we do if the guess is good enough?
• What should we do if the guess isn't good enough?

Instead of just outputting a guess, we want it to check to see if the guess is good enough. If it isn't, we want to improve it. If it is good enough, we want to output it. (You might think we'd want to print it, but that's not a good idea if we want to use this program for other tasks later.)

We come up with something like:

```to improve_guess :guess
if (good_enough :guess) output :guess
output improve_guess :guess - (function :guess) / (derivative :guess)
end
```
This procedure requires a helper procedure (predicate) good_enough, which looks like:
```to good_enough :guess
output lessp abs function :guess .01
end
```
(Draw a plumbing diagram for output lessp abs function :guess .01. What does it do? Will this work?)

We can now test procedure improve_guess. If it doesn't work, we'll have to debug it. If it works, we can think about writing a nice, chatty procedure that asks for a guess and prints the solution. We could also think about ways of stopping improve_guess if Newton's method cannot find a solution, and about ways of allowing the user to type in a function as well as a guess.

### More on Recursion

We've written a maze game like this one:
```to maze.game
print [You are lost in a cave.  Will you go left or right?]
if equalp readword "right [print [You are saved!] stop]
maze.game
end
```
This is an example of a recursive procedure. Recursive procedures have the following two properties:
• The procedure uses itself as a helper procedure. This is called the recursive call.
• The procedure must eventually end in a stop condition. In the example above, the procedure stops when the player turns right.
You may be familiar with inductive proofs or recursive definitions from your math classes. Proofs by induction use the following two ingredients:
• The proof of the theorem for larger values (inductive step) relies on its being true for smaller values (inductive hypothesis).
• The proof must start with a "base case" in which the theorem is shown to be true for the smallest values.
In proof by induction, the stop condition is like the base case and the recursive call is analogous to the inductive step. The inductive hypothesis in a proof by induction is like the leap of faith discussed in Chapter 8.

Recursive definitions are even more closely related to recursive procedures.Here's a recursive definition of n!, the factorial function:

• 0! = 1
• n! = n * (n-1)!
Here's a recursive procedure that computes factorials:
```to factorial :number
if equalp :number 0 [output 1]
output :number * factorial (:number - 1)
end
```
What's the stop condition? Where is the recursive call? Is this procedure an operation or command? What else do you notice about this procedure?

#### Variables and Recursion

In procedure factorial, the value of variable number changes as the procedure is run, and the output of factorial depends on the value input. To do something like split a list into two parts, we need to be comfortable using variables in recursive procedures.

The procedure below accepts a length as input and draws a spiral shape whose longest leg is that length.

```to spiral :length
if lessp :length 1 [stop]
forward :length
right 60
spiral (:length - 10)
end
```
What is the stop condition? Where is the recursive call in spiral?

Play around with the spiral procedure -- what happens if you change the 60 or the 10? What happens if you change the order the instructions appear? Why?

Next, see if you can write a procedure that takes a number as input and displays a countdown from that number to 0. Use the spiral procedure as your guide. If you are successful, see if you can write a procedure to count up from 0 to the number input.

Can you write a Logo procedure that accepts a list as input and displays each member of the list alone on the screen? The Logo primitives first, butfirst and emptyp may be helpful here, or you might use count and item.

Next, see if you can write a maze game that "keeps score" -- each time the user makes a turn without escaping, add one to the score. When the player escapes, print their final score.

#### Common Mistakes in Recursion

Below is a recursive version of a procedure which counts down to 0. Save your work (save "W:/Private/recursionlesson.txt) before running it:

```to countdown.recursive :number
print :number
countdown.recursive (:number-1)
end
```
Use the Logo menu to stop Logo. What went wrong?

Page 137 of Chapter 7 discusses the need for a stop rule that detects when a program has finished. In the case of countdown.recursive, you want to stop when the count reaches zero. Since your input might not be a positive integer, it's a good idea to play it safe and stop when the count is less than or equal to zero:

```to countdown.recursive :number
ifelse (greaterp :number 0)~
[print :number
countdown.recursive (:number-1)
]~
[print "Blastoff!]
end
```
Note that you have to check to see if it's time to stop before the procedure runs itself as a helper procedure. Otherwise it goes into an infinite loop and doesn't stop to check if it's done. The procedure below provides an example of this common mistake -- save your work before running it.

```to countdown.recursive2 :number
print :number
countdown.recursive2 (:number-1)
if (lessp :number 1) [print "Blastoff! stop]
end
```

#### stop

Remember our old writers.quiz procedure:
```to writers.quiz
print [Who is the greatest writer ever?]
if equalp readlist [Tolkien] [print [Yes, that's right!] stop]
print [No, silly, it's Tolkien]
end
```
Here Logo's stop command is used to end the command writers.quiz before the instruction print [No, silly, it's Tolkien] is run. Try removing the stop command, and see what happens. stop is a command which forces the procedure it's in to quit. The textbook has an example of the use of stop to quit early in a procedure which uses the quadratic formula. In countdown.recursive2 we used it to stop a recursive procedure. In most other situations, it's best to try to avoid using stop. We used an if command to see if the countdown was finished. We could also have used ifelse, as in the example in the textbook.
```to countdown.recursive3 :number
ifelse (greaterp :number 1)~
[print :number
countdown.recursive3 (:number-1)
]~
[print "Blastoff!]
end
```
If you do the extra credit game project, you may find that the last few lines of some procedure are run over and over when the program completes. This is usually caused by using if rather than ifelse at a decision point. Remember that when the the if statement completes, the computer will move on to run the next line of Logo code, even if you don't want it to! Experiment with procedure brokenmaze below to see what can happen. Can you fix brokenmaze so that it only prints At last! You escaped! once when you run it?

```to brokenmaze
print [You are lost in a maze.  Which way will you turn?]