RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

26
RECURSION • Recursion • Towers of Hanoi • To Recurse or to Loop? • Fractals Do something! Do something! Do something! Do something!

Transcript of RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

Page 1: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

RECURSION

• Recursion

• Towers of Hanoi

• To Recurse or to Loop?

• Fractals

Do something!

Do something!

Do something!

Do something!

Page 2: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 2 of 26

Three Teachers Want Cookies

• They would each like to have one of these cookies:

• How many ways can they distribute the cookies among themselves?– the first teacher who picks has three choices– only two choices left for second teacher– last teacher has to take what remains

• Thus we have six different ways three teachers can choose cookies (3 x 2 x 1 = 6)

• What if we wanted to solve this problem for all students in this class?

Page 3: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 3 of 26

Factorial Function

• Model this problem mathematically– factorial (n!) calculates total number of unique

permutations of n items

• Small examples:– 1! = 1– 2! = 2– 3! = 6– 4! = 24– 5! = 120

• Iterative definition– n! = n * (n - 1) * (n - 2) * ... * 1

• Recursive definition– n! = n * (n - 1)!– and 0! = 1

Page 4: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 4 of 26

Recursion

• Models problems that are self-similar– decompose whole task into smaller, simpler sub-

tasks that are similar– thus, each sub-task can be solved by applying

similar technique

• Whole task solved by combining solutions to sub-tasks– special form of divide and conquer

• Task is defined in terms of itself– in Java, modeled by method that calls itself– requires base case (case simple enough to be

solved directly, without recursion) to end recursion; otherwise infinite recursion

– what is base case of Factorial problem?

Page 5: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 5 of 26

Coding Factorial Function

• Recursive algorithm– note Factorial method assumes num >= 0– such assumptions are commonly called

preconditions and should be documented (or better yet, tested for)

public class RecursiveMath { // code elided static public long factorial(int num) { double result = 0; // base case: 0! = 1 if (num == 0) result = 1;

// general case: n! = n * (n - 1)! else result = num * this.factorial(num - 1);

return result;

}}

• Number of times method is called = depth of recursion– what is depth of (4!) ?

Page 6: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 6 of 26

Tower of Hanoi

• Game invented by French mathematician Edouard Lucas in 1883

• Goal: move tower of n disks, each of different size, from left-most peg to right-most peg

• Rule 1: no disk can be placed on top of smaller disk

• Rule 2: only one disk can be moved at once

Page 7: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 7 of 26

Pseudocode for Tower of Hanoi

• Try solving for 5 non-recursively. . .

• One disk:– move disk to final pole

• Two disks:– use one disk solution to move top disk to

intermediate pole– use one disk solution to move bottom disk to final

pole– use one disk solution to move top disk to final pole

• Three disks– use two disk solution to move top disks to

intermediate pole– use one disk solution to move bottom disk to final

pole– use two disk solution to move top disks to final pole

• In general (for n disks)– use n - 1 disk solution to move top disks to

intermediate pole– use one disk solution to move bottom disk to final

pole– use n - 1 disk solution to move top disks to final pole

• Note: can have multiple recursive calls

Page 8: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 8 of 26

Lower level pseudocode

//n is number of disks, src is starting pole//dst is finishing polepublic void hanoi(int n, Pole src, Pole dst) {if (n == 1) this.move(src, dst);else { Pole other = this.otherPole(src, dst); this.hanoi(n-1, src, other); this.move(src, dst); this.hanoi(n-1, other, dst);}

}

public Pole otherPole(Pole p1, Pole p2) { //returns the pole that is neither p1 nor p2

}

public void move(Pole src, Pole dst) { //take the top disk on the pole src and make

//it the top disk on the pole dst}

• That’s it! otherPole and move are fairly simple methods, so this is not much code.

• But try hand simulating this when n is greater than 4! Whoo boy, is it tough!

• The iterative solution is far more complex, and much harder to understand.

Page 9: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 9 of 26

Call Out the Turtles

• Use turtle to draw fractal shapes:– complex shapes that are composed of smaller,

simpler copies of some pattern– branch of mathematics developed by Benoit

Mandelbrot: characteristic is self-similarity– natural for recursion!

• Some examples:– spiral, tree, and snowflake

• Let’s start with the simplest: a spiralThe spiral starts at a particular point. It is made of successively shorter lines, each line at an angle to the previous one. The length of the first side (the longest one), spiral’s angle, and amount by which to decrement spiral’s sides can be specified by the user.

Page 10: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 10 of 26

Designing Spiral Class

• Spiral class defines single draw method– uses turtle to draw, so class needs reference to Turtle instance

• To make Spiral interesting, allow user many parameters to control its properties:– position at which spiral starts is turtle’s position– length of spiral’s starting side– angle between successive line segments– amount to change length of spiral’s sides

public class Spiral { private Turtle _turtle; private double _angle; private int _lengthDecrement; public Spiral(Turtle myTurtle, double myAngle, int myLengthDecrement) { _turtle = myTurtle;

_angle = myAngle; _lengthDecrement = 1; // default handles // bad parameters if (myLengthDecrement > 0) _lengthDecrement = myLengthDecrement; } // draw method defined soon... }

Page 11: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 11 of 26

Drawing Spiral

• First Step: Move turtle forward to draw line and turn some degrees. What’s next?

• Draw smaller line and turn! Then another, and another...

Page 12: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 12 of 26

Sending Recursive Messages

• draw method uses turtle to trace spiral:

public void draw(int sideLen) {

// base case: spiral too small to see if (sideLen <= 3) return;

// general case: move sideLen, turn angle, // and draw smaller spiral _turtle.forward(sideLen); _turtle.left(_angle); this.draw(sideLen - _lengthDecrement);}

• How does draw method divide up work?– draw first side of spiral:_turtle.forward(sideLen);_turtle.left(_angle);

– then draw smaller spiralthis.draw(sideLen - _lengthDecrement);

• What is base case?– when spiral is too small to see, conditional stops

method so no more recursive calls are madeif (sideLen <= 3) return;

– since side length must approach zero to terminate recursion, recursive calls to draw pass smaller side length each time

Page 13: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 13 of 26

Send in the Clones: Multiple Method Activations

• Recursive methods– we are used to a method containing different

message sends to this, but now we send the same message to this

– method must handle successively smaller versions of original task

• Method’s variable(s):– as with separate methods, each invocation

(message send) has its own copy of parameters and local variables, and shares access to instance variables

– record of code, all parameters and local variables is called activation record

• With recursion,– many activations of single method may exist at

once– at base case, as many exist as depth of recursion– each has its own copy of local variables,

parameters– each activation of a method is stored on the

“activation stack”• you’ll learn what stacks are shortly!

Page 14: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 14 of 26

Multiple Method Activations Illustrated

Spiral

draw(int sideLen)

draw Activation

int sideLen = 25

draw Activation

int sideLen = 14

draw Activation

int sideLen = 3

activation of draw method

activation of draw method

activation of draw method

recursion unwinds after reaching base case

Initial value of sideLen = 25

For length decrement = 11

Page 15: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 15 of 26

Loops vs. Recursion

• Spiral uses simple form of recursion– each sub-task only calls on one other sub-task– can be used for same computational tasks as

iteration– loops and simple recursion are computationally

equivalent

• Iterative definition of spiral:

public void drawIteratively(int sideLen) { while (sideLen > 3) { _turtle.forward(sideLen); _turtle.left(_angle); sideLen -= _lengthDecrement; }}

• Choice between simple recursion and iteration is one of modeling– recursion is often less efficient because of more

method calls (each activation record takes up some of computer’s memory)

– recursion is more concise and more elegant for tasks that are “naturally” self-similar• like Towers of Hanoi!

• Let’s see more complicated example of recursion!

Page 16: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 16 of 26

Fractal TreeThe tree is composed of a trunk that splits into two, smaller branches that sprout in opposite directions at the same angle. Each branch then splits as the trunk did until the sub-branch can no longer be seen, then it is drawn as a leaf. The length of a tree’s main trunk, angle at which branches sprout, and amount to decrement each branch can be specified by user.

• Compare each left branch to corresponding right branch:– right branch is simply rotated copy of left branch

• Branches are themselves smaller trees!– branches are themselves smaller trees!

• branches are themselves smaller trees!...

• Our tree is recursive!– base case is leaf

Page 17: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 17 of 26

Fractal Images

Pictures taken from HAL’s Legacy: 2001’s computer as dream and reality, edited by David G. Stork. MIT Press,

Cambridge Massachusetts: 1997

Page 18: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 18 of 26

Designing Tree Class

• Tree class defines single draw method– like Spiral, also uses turtle to draw, so let’s factor that

into a TurtleDrawer superclass– TurtleDrawer will just be a superclass of all things

that are drawn by an instance of Turtle; has protected _turtle instance variable. It’s protected so that each subclass has access to it to send it its own specialized command sequences for each subclass which we don’t want to include in superclass.

– Tree, Spiral extend TurtleDrawer superclass

• Tree has properties that user can set:– position at which tree starts (myTurtle’s built in

position)– angle between branches (myBranchAngle)– amount to change length of branches

(myTrunkDecrement)public class Tree extends TurtleDrawer { private double _branchAngle; private int _trunkDecrement;

public Tree(Turtle myTurtle, double myBranchAngle, int myTrunkDecrement) { super(myTurtle); _trunkDecrement = 1; _branchAngle = myBranchAngle; if (myTrunkDecrement > 0) _trunkDecrement = myTrunkDecrement; } // draw method defined soon...}

Page 19: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 19 of 26

Multiple Recursive Message Sends

public void draw(int trunkLen) { // base case: branch too small, so draw leaf if (trunkLen <= 0) { this.stampLeaf(); // method to draw a leaf // at turtle’s position // general case: draw tree as trunk with two // smaller trees rotated by _branchAngle } else { // draw trunk -- use inherited _turtle variable _turtle.forward(trunkLen); // recursively draw left branch after orienting _turtle.left(_branchAngle); this.draw(trunkLen - _trunkDecrement); // recursively draw right branch // after orienting

_turtle.right(2.0 * _branchAngle); this.draw(trunkLen - _trunkDecrement); // back up to prepare for next branch _turtle.left(_branchAngle); _turtle.back(trunkLen); }}

public void stampLeaf() { Shape.Ellipse leaf = new Shape.Ellipse(_turtle.getPanel());

leaf.setLocation(_turtle.getLocation()); leaf.setColor(java.awt.Color.green);}

recursive call

Page 20: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 20 of 26

Recursive Snowflake

• Invented by Swedish mathematician, Helge von Koch, in 1904; also known as Koch IslandThe snowflake is created by taking an equilateral triangle and partitioning each side into three equal parts. Each side’s middle part is then replaced by another equilateral triangle (with no base) whose sides are one third as long as the original. This process is repeated for each remaining line segment. The length of the initial equilateral triangle’s side can be given by the user.

• Design of RecursiveSnowflake class is similar to Tree and Spiral– extends TurtleDrawer class

Page 21: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 21 of 26

Recursive Snowflake draw Method

• Recursive snowflake is basically a triangle– can draw equilateral triangle iteratively

public void draw(int sideLen) { for (int i = 0; i < 3; i++) { _turtle.forward(sideLen); _turtle.right(120.0); }}

• To make point on snowflake, split each side with smaller triangle instead of only moving forward– smaller triangle is one-third size– since no base, can draw with only four segmentspublic void drawSide(int sideLen) { _turtle.forward(Math.round(sideLen / 3.0)); _turtle.left(60.0); _turtle.forward(Math.round(sideLen / 3.0)); _turtle.right(120.0); _turtle.forward(Math.round(sideLen / 3.0)); _turtle.left(60.0); _turtle.forward(Math.round(sideLen / 3.0));}

• Of course, each of these smaller sides can be split with smaller triangles, which can be split with even smaller triangles, etc., so we need to make drawSide() recursive

Page 22: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 22 of 26

Using Recursive Helper Methods /** * This method draws recursive snowflake by * drawing smaller, rotated triangles on each * side of the triangle. */ public void draw(int sideLen) { for (int i = 0; i < 3; i++) { this.drawSide(sideLen); _turtle.right(120.0); } }

/** * This method draws single side of recursive * snowflake by drawing four recursive sides. */ private void drawSide(int sideLen) { // base case: simply draw a straight side. // Define the constant MIN_SIDE to be the // smallest side we draw, in this case, 20. if (sideLen < MIN_SIDE) { _turtle.forward(sideLen); // general case: draw complete recursive side } else { this.drawSide(Math.round(sideLen / 3)); _turtle.left(60.0); this.drawSide(Math.round(sideLen / 3)); _turtle.right(120.0); this.drawSide(Math.round(sideLen / 3)); _turtle.left(60.0); this.drawSide(Math.round(sideLen / 3)); }}

Page 23: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 23 of 26

Let’s Hand Simulate

• First, call draw(90). It calls drawSide(90)– that calls drawSide(30)• drawSide(30) calls drawSide(10) which tells turtle to

go forward 10 steps. Then drawSide(10) returns to

• drawSide(30), which tells turtle to turn left 60 degrees. It then calls drawSide(10) again which tells turtle to go forward 10 steps. Then drawSide(10) returns to

• drawSide(30), which tells turtle to turn right 120 degrees. It then calls drawSide(10) again which tells turtle to go forward 10 steps. Then drawSide(10) returns to

• drawSide(30), which tells turtle to turn left 60 degrees. It then calls drawSide(10) again which tells turtle to go forward 10 steps. Then drawSide(10) returns to

• drawSide(30). We’re done with first drawSide(30) so return to drawSide(90) which tells turtle to turn left 60 degrees. It then calls drawSide(30) again, etc.

Page 24: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 24 of 26

Recursive Snowflake Step-by-Step

• Colored triangles added for emphasis only.

Page 25: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 25 of 26

Other Types of Recursion

• Indirect recursion– two or more methods act recursively instead of

just one– methods may be implemented in same or different

objects– for example: methodA calls methodB which calls

methodA again

Page 26: RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!

October 18, 2005Recursion 26 of 26