Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


Presentation on theme: "RECURSION Recursion Towers of Hanoi To Recurse or to Loop? Fractals Do something!"— Presentation transcript:

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

2 October 18, 2005Recursion2 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?

3 October 18, 2005Recursion3 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

4 October 18, 2005Recursion4 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?

5 October 18, 2005Recursion5 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!) ?

6 October 18, 2005Recursion6 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

7 October 18, 2005Recursion7 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

8 October 18, 2005Recursion8 of 26 Lower level pseudocode //n is number of disks, src is starting pole //dst is finishing pole public 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.

9 October 18, 2005Recursion9 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 spiral The 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.

10 October 18, 2005Recursion10 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... }

11 October 18, 2005Recursion11 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...

12 October 18, 2005Recursion12 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 spiral this.draw(sideLen - _lengthDecrement); What is base case? –when spiral is too small to see, conditional stops method so no more recursive calls are made if (sideLen <= 3) return; –since side length must approach zero to terminate recursion, recursive calls to draw pass smaller side length each time

13 October 18, 2005Recursion13 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!

14 October 18, 2005Recursion14 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 recursion unwinds after reaching base case Initial value of sideLen = 25 For length decrement = 11

15 October 18, 2005Recursion15 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!

16 October 18, 2005Recursion16 of 26 Fractal Tree The 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

17 October 18, 2005Recursion17 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

18 October 18, 2005Recursion18 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... }

19 October 18, 2005Recursion19 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

20 October 18, 2005Recursion20 of 26 Recursive Snowflake Invented by Swedish mathematician, Helge von Koch, in 1904; also known as Koch Island The 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

21 October 18, 2005Recursion21 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 segments public 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

22 October 18, 2005Recursion22 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)); } }

23 October 18, 2005Recursion23 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.

24 October 18, 2005Recursion24 of 26 Recursive Snowflake Step-by-Step Colored triangles added for emphasis only.

25 October 18, 2005Recursion25 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

26 October 18, 2005Recursion26 of 26


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

Similar presentations


Ads by Google