1 cs 410 / 510 mastery in programming chapter 2 recursion herbert g. mayer, psu cs status 7/6/2013...

35
1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Herbert G. Mayer, PSU CS Status 7/6/2013 Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer With improvements suggested by: Gaby Haddock, summer 2013 2013

Upload: sybil-armstrong

Post on 12-Jan-2016

213 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

1

CS 410 / 510 Mastery in Programming

Chapter 2Recursion

Herbert G. Mayer, PSU CSHerbert G. Mayer, PSU CSStatus 7/6/2013Status 7/6/2013

With improvements suggested by: Gaby Haddock, summer With improvements suggested by: Gaby Haddock, summer 20132013

Page 2: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

2

Syllabus Definition of Recursive AlgorithmDefinition of Recursive Algorithm Recursion vs. IterationRecursion vs. Iteration Q-SequenceQ-Sequence Ackermann FunctionAckermann Function Stack Data StructureStack Data Structure Simulate Recursion via IterationSimulate Recursion via Iteration ReferencesReferences

Page 3: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

3

Definition of Recursive Algorithm

An algorithms is recursive, if it is An algorithms is recursive, if it is partlypartly defined by simpler versions defined by simpler versions of itself [1]of itself [1]

A recursive program is the implementation of a recursive algorithm What is the key problem for a programmer, using a language that is non-

recursive (e.g. standard Fortran) if the algorithm to be implemented is recursive? --See later!

What then are the What then are the other partsother parts of a recursive algorithm? of a recursive algorithm? Correct recursive algorithm requires a starting point, formally known as “base case”

Base case could be multiple steps

Recursive algorithm Recursive algorithm a() a() uses a base case as starting point for uses a base case as starting point for computation, plus the actual function body, including some recursive computation, plus the actual function body, including some recursive use of use of a()a()

Recursive body can be Recursive body can be indirectly recursiveindirectly recursive through intermediate function through intermediate function a()-> b()-> a() – through intermediate function b()

Primitive examples are the factorial( n ) function; or Fibonacci( n ), Primitive examples are the factorial( n ) function; or Fibonacci( n ), for non-negative arguments n; Fibo( n ) shown here:for non-negative arguments n; Fibo( n ) shown here:

Base case 1: Fibo(0) = 0 Base case 2: Fibo(1) = 1 Recursive Definition: Fibo( n ) for n > 1 = Fibo( n-1 ) + Fibo( n-2 )

Page 4: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

4

Recursion vs. IterationIteration is expressed in programming Iteration is expressed in programming

languages by loops; e.g. languages by loops; e.g. for-, while-, for-, while-, do-, do-, or or repeatrepeat loops loops

These are readable and efficient methods for These are readable and efficient methods for expressing iteration, but are expressing iteration, but are not strictly not strictly necessarynecessary

Recursion can replace iterative steps; yet Recursion can replace iterative steps; yet for some people this seems counter-for some people this seems counter-intuitiveintuitive

Neophytes are sometimes unused to recursion; Neophytes are sometimes unused to recursion; yet recursion can be as intuitive as yet recursion can be as intuitive as simple iteration simple iteration

Page 5: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

5

Replace Iteration via RecursionUsing only Using only functionsfunctions, called recursively, called recursively

PlusPlus arithmetic increment/decrement arithmetic increment/decrement operators operators ++ --++ -- and unary minus and unary minus ––

And conventional relational operators And conventional relational operators > >= !> >= != = etc.etc.

All other operators are dis-allowed in this All other operators are dis-allowed in this experiment, i.e. no experiment, i.e. no + - * / % **+ - * / % ** etc.etc.

Page 6: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

6

Recursion vs. Iteration: add()// return a // return a ++ b without b without + + operation!operation!int add( int a, int b )int add( int a, int b ){ // add{ // addif ( 0 == b ) {if ( 0 == b ) {

return a;return a;}else if ( b < 0 ) {}else if ( b < 0 ) {

return add( --a, ++b );return add( --a, ++b );}else{}else{

return add( ++a, --b );return add( ++a, --b );} //end if} //end if

} //end add} //end add

Page 7: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

7

Recursion vs. Iteration: sub()

// return a // return a –– b; no dyadic b; no dyadic – – operationoperationint sub( int a, int b )int sub( int a, int b ){ // sub{ // subreturn add( a, -b );return add( a, -b );

} //end sub} //end sub

Page 8: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

8

Recursion vs. Iteration: mult()// return a // return a ** b, no b, no ** but add() but add()int mult( int a, int b )int mult( int a, int b ){ // mult{ // multif ( 0 == b ) {if ( 0 == b ) {

return 0;return 0;}else if ( 1 == b ) {}else if ( 1 == b ) {

return a;return a;}else if ( b < 0 ) {}else if ( b < 0 ) {

return -mult( a, -b );return -mult( a, -b );}else{}else{

// b > 0// b > 0return add( a, mult( a, --b ) );return add( a, mult( a, --b ) );

} //end if} //end if} //end mult} //end mult

Page 9: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

9

Recursion vs. Iteration: expo()// return a // return a ** ** b, no b, no **** op in C++; requires mult( int, int ) op in C++; requires mult( int, int )int expo( int a, int b )int expo( int a, int b ){ // expo{ // expo if ( 0 == a ) {if ( 0 == a ) { if ( 0 == b ) {if ( 0 == b ) { printf( ”undefined value0^0\n" );printf( ”undefined value0^0\n" ); }else if ( b < 0 ) {}else if ( b < 0 ) { printf( “0 to <0 power is undefined\n" );printf( “0 to <0 power is undefined\n" );

} //end if} //end if return 0;return 0;

}else if ( 0 == b ) {}else if ( 0 == b ) { return 1;return 1; }else if ( 1 == a ) {}else if ( 1 == a ) { return 1;return 1; }else if ( -1 == a ) {}else if ( -1 == a ) { return b % 2 ? -1 : 1;return b % 2 ? -1 : 1; }else if ( b < 0 ) {}else if ( b < 0 ) { return 0;return 0; }else{}else{ return mult( expo( a, --b ), a );return mult( expo( a, --b ), a ); } //end if} //end if} //end expo} //end expo

Page 10: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

10

Q-Sequence, DefinitionQ-Sequence defined by Q-Sequence defined by Douglas HofstadterDouglas Hofstadter in [1] as a in [1] as a

function function q( n ) q( n ) for positive integers n > 0for positive integers n > 0

Base case n = 1: q(1) = 1Base case n = 1: q(1) = 1Base case n = 2: q(2) = 1Base case n = 2: q(2) = 1

Recursive definition of q(n), for positive n > 2Recursive definition of q(n), for positive n > 2

q( n ) = q( n – q( n - 1 ) ) + q( n – q( n - 2 ) )q( n ) = q( n – q( n - 1 ) ) + q( n – q( n - 2 ) )

Q-Sequence reminds us of Q-Sequence reminds us of Fibonacci( n )Fibonacci( n ) function, but with function, but with surprising difference in the type of result:surprising difference in the type of result:

By contract, the function results of By contract, the function results of fibonacci( n )fibonacci( n ) are are monotonically increasing with increasing argumentmonotonically increasing with increasing argument

Results of Results of q( n )q( n ) are non-monotonic!are non-monotonic!

Note # of calls:Note # of calls: calls(q( 40 )) = calls(q( 40 )) = 1,137,454,7411,137,454,741

Page 11: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

11

Q-Sequence, Coded in C#define MAX 100#define MAX 100 // arbitrary limit; never reached!!!!// arbitrary limit; never reached!!!!int calls;int calls; // will be initialized each time// will be initialized each time

int q( int arg )int q( int arg ){ // q{ // q

calls++;calls++; // track another call// track another callif ( arg <= 2 ) {if ( arg <= 2 ) { return 1;return 1; // base case// base case}else{}else{ // now recurse!// now recurse! return q( arg - q( arg-1 ) ) + q( arg - q( arg-2 ) );return q( arg - q( arg-1 ) ) + q( arg - q( arg-2 ) );} // end if} // end if

} // end q} // end q

void main()void main(){ // main{ // main

for( int i = 1; i < MAX; i++ ) {for( int i = 1; i < MAX; i++ ) { calls = 0;calls = 0; // initially no calls yet// initially no calls yet printf( "Q(%2d) = %3d, #calls = %10d\n", i, q(i), printf( "Q(%2d) = %3d, #calls = %10d\n", i, q(i), calls );calls );} // end for} // end for

} // end main} // end main

Page 12: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

12

Q-Sequence ResultsQ( 1) = 1, #calls = 1Q( 1) = 1, #calls = 1Q( 2) = 1, #calls = 1Q( 2) = 1, #calls = 1Q( 3) = 2, #calls = 5Q( 3) = 2, #calls = 5Q( 4) = 3, #calls = 13Q( 4) = 3, #calls = 13Q( 5) = 3, #calls = 25Q( 5) = 3, #calls = 25Q( 6) = 4, #calls = 49Q( 6) = 4, #calls = 49Q( 7) = 5, #calls = 93Q( 7) = 5, #calls = 93Q( 8) = 5, #calls = 161Q( 8) = 5, #calls = 161Q( 9) = 6, #calls = 281Q( 9) = 6, #calls = 281Q(10) = 6, #calls = 481Q(10) = 6, #calls = 481Q(11) = 6, #calls = 813Q(11) = 6, #calls = 813

. . .. . .

Q(26) = 14, #calls = 1341433Q(26) = 14, #calls = 1341433Q(27) = 16, #calls = 2174493Q(27) = 16, #calls = 2174493Q(28) = 16, #calls = 3521137Q(28) = 16, #calls = 3521137Q(29) = 16, #calls = 5700281Q(29) = 16, #calls = 5700281Q(30) = 16, #calls = 9229053Q(30) = 16, #calls = 9229053Q(31) = 20, #calls = 14941993Q(31) = 20, #calls = 14941993Q(32) = 17, Q(32) = 17, #calls = 24182797#calls = 24182797Q(33) = 17, #calls = 39137473Q(33) = 17, #calls = 39137473Q(34) = 20, #calls = 63354153Q(34) = 20, #calls = 63354153Q(35) = 21, #calls = 102525697Q(35) = 21, #calls = 102525697Q(36) = 19, Q(36) = 19, #calls = 165896537#calls = 165896537Q(37) = 20, #calls = 268460333Q(37) = 20, #calls = 268460333Q(38) = 22, #calls = 434429737Q(38) = 22, #calls = 434429737Q(39) = 21, Q(39) = 21, #calls = 702952137#calls = 702952137Q(40) = 22, #calls = 1137454741Q(40) = 22, #calls = 1137454741

. . . Will never reach Q(100) in your life time . . . Will never reach Q(100) in your life time

Page 13: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

13

Ackermann Definition

Ackermann a( m, n ) is defined as a function Ackermann a( m, n ) is defined as a function of two non-negative integers m and nof two non-negative integers m and n

Base case 1: a( 0, n ) = n + 1Base case 1: a( 0, n ) = n + 1Base case 2: a( m, 0 ) = a( m - 1, 1 )Base case 2: a( m, 0 ) = a( m - 1, 1 )

Recursive definition of a( m, n ), m, n > 0Recursive definition of a( m, n ), m, n > 0a( m, n ) = a( m - 1, a( m, n - 1 ) )a( m, n ) = a( m - 1, a( m, n - 1 ) )

Ackermann complexity grows awfully fast; e.g. Ackermann complexity grows awfully fast; e.g. a(4,2) a(4,2) is an integer number with 19,729 is an integer number with 19,729 decimal digits; greater than the national US decimal digits; greater than the national US debt! debt!

Page 14: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

14

Ackermann Definition

Students, code now in C, volunteers shows Students, code now in C, volunteers shows result on white-board:result on white-board:

Base case 1: a( 0, n ) = n + 1Base case 1: a( 0, n ) = n + 1Base case 2: a( m, 0 ) = a( m - 1, 1 )Base case 2: a( m, 0 ) = a( m - 1, 1 )

Recursive definition of a( m, n ), m, n > 0Recursive definition of a( m, n ), m, n > 0a( m, n ) = a( m - 1, a( m, n - 1 ) )a( m, n ) = a( m - 1, a( m, n - 1 ) )

Page 15: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

15

Ackermann Coded in C

unsigned a( unsigned m, unsigned n )unsigned a( unsigned m, unsigned n ){ // a{ // a

calls++;calls++; // global unsigned// global unsignedif ( 0 == m ) {if ( 0 == m ) { // note operand order// note operand order return n + 1;return n + 1; // first base case// first base case}else if ( 0 == n ) {}else if ( 0 == n ) { // m > 0// m > 0

return a( m - 1, 1 );return a( m - 1, 1 ); // other base case// other base case}else{}else{ // m > 0, n > 0// m > 0, n > 0

return a( m-1, a( m, n-1 ) );return a( m-1, a( m, n-1 ) ); // recurse!// recurse!} // end if} // end if

} // end q} // end q

void main()void main(){ // main{ // main

for( int i = 0; i < MAX; i++ ) {for( int i = 0; i < MAX; i++ ) { printf( "\nFor m = %d\n", i );printf( "\nFor m = %d\n", i ); for( int j = 0; j < MAX; j++ ) {for( int j = 0; j < MAX; j++ ) {

calls = 0;calls = 0; printf( "a(%1d,%1d) = %10u, calls = %12u\n",printf( "a(%1d,%1d) = %10u, calls = %12u\n",

i, j, a( i, j ), calls );i, j, a( i, j ), calls ); } // end for} // end for

} // end for} // end for} // end main} // end main

Page 16: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

16

Ackermann ResultsFor m = 0For m = 0a(0,0) = 1, calls = 1a(0,0) = 1, calls = 1. . .. . .

For m = 1For m = 1. . .. . .a(1,7) = 9, calls = 16a(1,7) = 9, calls = 16

For m = 2For m = 2a(2,0) = 3, calls = 5a(2,0) = 3, calls = 5a(2,1) = 5, calls = 14a(2,1) = 5, calls = 14a(2,2) = 7, calls = 27a(2,2) = 7, calls = 27a(2,3) = 9, calls = 44a(2,3) = 9, calls = 44a(2,4) = 11, calls = 65a(2,4) = 11, calls = 65a(2,5) = 13, calls = 90a(2,5) = 13, calls = 90a(2,6) = 15, calls = 119a(2,6) = 15, calls = 119a(2,7) = 17, calls = 152a(2,7) = 17, calls = 152

For m = 3For m = 3a(3,0) = 5, calls = 15a(3,0) = 5, calls = 15a(3,1) = 13, calls = 106a(3,1) = 13, calls = 106a(3,2) = 29, calls = 541a(3,2) = 29, calls = 541a(3,3) = 61, calls = 2432a(3,3) = 61, calls = 2432a(3,4) = 125, calls = 10307a(3,4) = 125, calls = 10307a(3,5) = 253, calls = 42438a(3,5) = 253, calls = 42438a(3,6) = 509, calls = 172233a(3,6) = 509, calls = 172233a(3,7) = 1021, calls = 693964a(3,7) = 1021, calls = 693964

For m = 4For m = 4a(4,0) = 13, calls = 107a(4,0) = 13, calls = 107

don’t even dream about computing a(4,2) don’t even dream about computing a(4,2) or higher! or higher!

Page 17: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

17

Stack Data Structure High-level language functions call each other in a High-level language functions call each other in a

nested fashion, recursively, evennested fashion, recursively, even indirectly indirectly recursivelyrecursively

And return in strictly the reverse order (LIFO), And return in strictly the reverse order (LIFO), but with any number of further calls in betweenbut with any number of further calls in between

Stack is the natural data structure to track Stack is the natural data structure to track callée return informationcallée return information

Languages also allow local data per function call, Languages also allow local data per function call, of which formal parameters are just one variationof which formal parameters are just one variation

Natural to have locals also live and die on the Natural to have locals also live and die on the run time stack, synchronized with call-return run time stack, synchronized with call-return informationinformation

Possible but wasteful to have a separate stack for Possible but wasteful to have a separate stack for automatic locals: conclusion to have unified stackautomatic locals: conclusion to have unified stack

Page 18: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

18

Other temps

0 or more locals

Field 1: Function return value

Caller pushes formals

0..32 registers saved

Field 2: return address

Field 3: dynamic link

Field 4: static link

sp

bp

hp

Stack Marker

Stack Frame

Stack Frame of callee

Stack growsdownwardsStack growsdownward

Page 19: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

19

Stack Data Structure Stack is natural data structure for recursive call:Stack is natural data structure for recursive call:

1.) Before call: provide (push) all actual parameters During the call, these are the formal parameters 2.) Then execute call, provide the return address on stack Provide space on stack for return value if needed (function) And push bp register, pointing to the frame of caller: known

as dynamic link 3.) Before executing callée code: allocate locals on stack And allocate temps, e.g. copies of all regs to be used, save

them and later restore before return

Thus stack grows by 3 physical + logical sections:Thus stack grows by 3 physical + logical sections: Formal parameters, some of them just addresses for & Stack Marker, AKA Activation Record: RA, RV, Dynamic Link Locals + temps+ saved regs

Page 20: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

20

Stack Data Structure Stack is addressed by 2 HW resources, typically Stack is addressed by 2 HW resources, typically

registers registers bpbp and and sp sp (AKA (AKA toptop)) It is computable to have a single register address stack It is computable to have a single register address stack

via current frame, since the compiler “knows” at each via current frame, since the compiler “knows” at each place, by how much stack must have grownplace, by how much stack must have grown

Actually so done by Actually so done by GreenhillsGreenhills compilers in 1990s for compilers in 1990s for register-starved Intel architectureregister-starved Intel architecture

Base Pointer register Base Pointer register bpbp points to some defined place of points to some defined place of stack marker, typically to stack marker, typically to dynamic linkdynamic link

The top of stack register The top of stack register spsp points to the dynamically points to the dynamically changing, momentary top of stack –changing, momentary top of stack –dynamic = during the dynamic = during the callcall

The The bpbp stays invariant during the call; changes only at stays invariant during the call; changes only at further calls and at any returns –further calls and at any returns –static = during the static = during the callcall

The The spsp changes with each call preparation, each temp changes with each call preparation, each temp pushed on top, each intermediate result, etc.pushed on top, each intermediate result, etc.

Page 21: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

21

Simulate Recursion via Iteration• Important for master programmer to understand RT-Important for master programmer to understand RT-

stack and recursion!stack and recursion!• What to do, if you implement a recursive algorithm What to do, if you implement a recursive algorithm

using a language that does not support recursion?using a language that does not support recursion?• Replace recursive by a non-recursive algorithm!Replace recursive by a non-recursive algorithm!• Or simulate recursion via non-recursive methodsOr simulate recursion via non-recursive methods• After all, a computer chip has no notion of After all, a computer chip has no notion of

recursion; it is a sequential machine that recursion; it is a sequential machine that ““simulates recursionsimulates recursion”” via non-recursive methods; via non-recursive methods; the compiler plus run-time system perform this the compiler plus run-time system perform this transformation!transformation!

• Done so at local industry in the past: Done so at local industry in the past: FPSFPS used used Fortran!! to implement System SW and compilersFortran!! to implement System SW and compilers

• Here are the actual steps of simulating recursion Here are the actual steps of simulating recursion via iteration; must use language with via iteration; must use language with GotoGoto – –terrible sin terrible sin

Page 22: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

22

Steps of Simulating Recursion

consider directly-recursive calls of simulated consider directly-recursive calls of simulated function:function:

1.1. Define data structure struct Define data structure struct stack_tpstack_tp, to hold params, , to hold params, locals, etc.locals, etc.

2.2. Define explicit stack with Define explicit stack with top of stacktop of stack ( (toptop) index, ) index, initially top=0; like a real stack identified by initially top=0; like a real stack identified by spsp, may , may overflow, so include code to check; overflow, so include code to check; stack[ top ]stack[ top ] holds holds parameters, function return value, return location (labels parameters, function return value, return location (labels after a recursive call), and automaticsafter a recursive call), and automatics

3.3. Define Define labelslabels for each for each point of recursive callpoint of recursive call, more , more precisely at each precisely at each point point after the callafter the call; number these ; number these points of return, e.g. l1, l2, l3, l4 etc. There shall be points of return, e.g. l1, l2, l3, l4 etc. There shall be branches=gotos to these branches=gotos to these points of returnpoints of return

4.4. At each point ofAt each point of recursive call recursive call::1. Increment : i.e. top++, like HW recursion that grows + shrinks sp2. Manually move parameters for “this call” onto stack; e.g. assign:

stack[ top ].arg1 = actual1; stack[ top ].arg2 = actual2 . .1. Store the place of return:

stack[ top ].ret = 1, or 2, or 3 alluding to l1, l2, l3 . . .1. Initialize local, automatic objects: stack[ top ].local1 =

value1 . . .2. Jump (Goto, the terrible sin!) to function head, not including

initializing code

Page 23: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

23

Steps of Simulating Recursion4. Point of return: In simple cases, all explicitly 4. Point of return: In simple cases, all explicitly

coded returns and the implied return at the end of the coded returns and the implied return at the end of the recursive function body can be re-coded into a single recursive function body can be re-coded into a single place; if not, the code to simulate a return is place; if not, the code to simulate a return is replicated:replicated: Decrement the top of stack index: top-- Check, to which of the stored labels the flow of control

has to branch to simulate return (via goto) to continue execution; e.g.:

if ( stack[ top+1 ].ret == xyz ) goto label_xyz;

And if no other branch is open, then fall through to the end

For void functions this is a literal fall-through For true functions, the return value has to be computed

before the fall-through, e.g.:return stack[ top ].return_val; // top is that of caller!

5. For nested recursive calls or several recursive calls 5. For nested recursive calls or several recursive calls in a row or both: in a row or both: ““be creativebe creative”” ; see an example ; see an example later; apply these steps with meticulous precisionlater; apply these steps with meticulous precision

Page 24: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

24

Simulate Recursion, fact()#include <stdio.h>#include <stdio.h>#define MAX_STACK 100#define MAX_STACK 100 // never reached or exceeded!// never reached or exceeded!#define MAX 14#define MAX 14 // higher factorial overflows 32bits// higher factorial overflows 32bits

unsigned calls = 0;unsigned calls = 0; // track # of calls// track # of calls

typedef struct s_tp {typedef struct s_tp {unsigned arg;unsigned arg; // for formal parameters// for formal parametersunsigned fact;unsigned fact; // function return value// function return valueunsigned ret;unsigned ret; // code address after call, return!// code address after call, return!

} struct_s_tp;} struct_s_tp;

// first the recursive fact() function for reference// first the recursive fact() function for reference// includes tracking # of calls// includes tracking # of callsunsigned fact( unsigned arg )unsigned fact( unsigned arg ){ // fact{ // fact

calls++;calls++; // gotta be global// gotta be globalif ( 0 == arg ) {if ( 0 == arg ) { // why strange order?// why strange order? return 1;return 1;}else{}else{ return fact( arg - 1 ) * arg;return fact( arg - 1 ) * arg;} // end if} // end if// // there should be an assertion here!there should be an assertion here!

} // end fact} // end fact

Page 25: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

25

Simulate Recursion, fact()unsigned nrfact( unsigned arg )unsigned nrfact( unsigned arg ){ // nrfact{ // nrfact

struct_s_tp s[ MAX_STACK ];struct_s_tp s[ MAX_STACK ]; // simulate // simulate RT stackRT stack!!unsigned top = 0;unsigned top = 0; // simulate // simulate spsp register registers[ top ].arg = arg;s[ top ].arg = arg; // this call’s argument// this call’s arguments[ top ].ret = 3;s[ top ].ret = 3; // 3 alludes to label // 3 alludes to label l3l3

l1:l1: if ( 0 == s[ top ].arg ) {if ( 0 == s[ top ].arg ) { s[ top ].fact = 1;s[ top ].fact = 1;}else{}else{ top++;top++; // recursion!// recursion! s[ top ].arg = s[ top-1 ].arg-1;s[ top ].arg = s[ top-1 ].arg-1; s[ top ].ret = 2;s[ top ].ret = 2; // remember label l2// remember label l2 gotogoto l1; l1; // now simulate recursion// now simulate recursion

l2:l2: // back from recursive call// back from recursive call top--;top--; // // sp--sp-- s[ top ].fact = s[ top + 1 ].fact * s[ top ].arg;s[ top ].fact = s[ top + 1 ].fact * s[ top ].arg;} // end if} // end ifif ( s[ top ].ret == 2 ) {if ( s[ top ].ret == 2 ) { // test, where to branch to// test, where to branch to gotogoto l2; l2; // // unstructured goto into ifunstructured goto into if} // end if} // end if

l3:l3:return s[ top ].fact;return s[ top ].fact;

} // end nrfact} // end nrfact

Page 26: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

26

Simulate Recursion, fact() Result

r_fact( 0) = 1, calls = 1r_fact( 0) = 1, calls = 1 r_fact( 1) = 1, calls = 2 r_fact( 1) = 1, calls = 2 r_fact( 2) = 2, calls = 3 r_fact( 2) = 2, calls = 3 r_fact( 3) = 6, calls = 4 r_fact( 3) = 6, calls = 4 r_fact( 4) = 24, calls = 5 r_fact( 4) = 24, calls = 5 r_fact( 5) = 120, calls = 6 r_fact( 5) = 120, calls = 6 r_fact( 6) = 720, calls = 7 r_fact( 6) = 720, calls = 7 r_fact( 7) = 5040, calls = 8 r_fact( 7) = 5040, calls = 8 r_fact( 8) = 40320, calls = 9 r_fact( 8) = 40320, calls = 9 r_fact( 9) = 362880, calls = 10 r_fact( 9) = 362880, calls = 10 r_fact(10) = 3628800, calls = 11 r_fact(10) = 3628800, calls = 11 r_fact(11) = 39916800, calls = 12 r_fact(11) = 39916800, calls = 12 r_fact(12) = 479001600, calls = 13 r_fact(12) = 479001600, calls = 13 r_fact(13) = 1932053504, calls = 14 r_fact(13) = 1932053504, calls = 14

nr_fact( 0) = 1nr_fact( 0) = 1nr_fact( 1) = 1nr_fact( 1) = 1nr_fact( 2) = 2nr_fact( 2) = 2nr_fact( 3) = 6nr_fact( 3) = 6nr_fact( 4) = 24nr_fact( 4) = 24nr_fact( 5) = 120nr_fact( 5) = 120nr_fact( 6) = 720nr_fact( 6) = 720nr_fact( 7) = 5040nr_fact( 7) = 5040nr_fact( 8) = 40320nr_fact( 8) = 40320nr_fact( 9) = 362880nr_fact( 9) = 362880nr_fact(10) = 3628800nr_fact(10) = 3628800nr_fact(11) = 39916800nr_fact(11) = 39916800nr_fact(12) = 479001600nr_fact(12) = 479001600nr_fact(13) = 1932053504nr_fact(13) = 1932053504

Page 27: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

27

Simulate Recursion, fibo()#define MAX_STACK 100#define MAX_STACK 100 // never to be reached or exceeded!// never to be reached or exceeded!#define MAX 30#define MAX 30 // higher fibo(n) not computable!// higher fibo(n) not computable!

unsigned calls;unsigned calls; // in case we track # of calls// in case we track # of calls

typedef struct s_tp {typedef struct s_tp { // type of stack// type of stackunsigned arg;unsigned arg; // copy of fibo’s arg// copy of fibo’s argunsigned fibo;unsigned fibo; // return value for fibo// return value for fibounsigned ret;unsigned ret; // to which label to goto?// to which label to goto?

} struct_s_tp;} struct_s_tp;

// recursive function for reference:// recursive function for reference:unsigned fibo( unsigned arg )unsigned fibo( unsigned arg ){ // fibo{ // fibo

calls++;calls++;if ( arg <= 1 ) {if ( arg <= 1 ) { // base case?// base case? return arg;return arg; // if so: done!// if so: done!}else{}else{ return fibo( arg-1 ) + fibo( arg-2 );return fibo( arg-1 ) + fibo( arg-2 );} // end if} // end if

} // end fibo} // end fibo

Page 28: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

28

Simulate Recursion, fibo()unsigned nr_fibo( unsigned arg )unsigned nr_fibo( unsigned arg ){ //nr_fibo{ //nr_fibo

struct_s_tp s[ MAX_STACK ];struct_s_tp s[ MAX_STACK ]; // stack can be local// stack can be local unsigned top = 0;unsigned top = 0; // initially// initially s[ top ].arg = arg;s[ top ].arg = arg; // copy arg to stack// copy arg to stack s[ top ].ret = 4;s[ top ].ret = 4; // if all fails, return// if all fails, return

l1: if ( s[ top ].arg <= 1 ) {l1: if ( s[ top ].arg <= 1 ) { s[ top ].fibo = s[ top ].arg;s[ top ].fibo = s[ top ].arg; }else{}else{ top++;top++; // ready to recurse// ready to recurse s[ top ].arg = s[ top - 1 ].arg - 1;s[ top ].arg = s[ top - 1 ].arg - 1; s[ top ].ret = 2;s[ top ].ret = 2; // to place of 1. return// to place of 1. return gotogoto l1; l1; // recurse!// recurse!

l2:l2: top++; top++; // ready to recurse again// ready to recurse again s[ top ].arg = s[ top - 2 ].arg - 2;s[ top ].arg = s[ top - 2 ].arg - 2; s[ top ].ret = 3;s[ top ].ret = 3; // to place of 2nd return// to place of 2nd return gotogoto l1; l1; // recurse!// recurse!

l3:l3: // two returns simulated// two returns simulated top -= 2;top -= 2; // simulate 2 returns// simulate 2 returns s[ top ].fibo = s[ top + 1 ].fibo + s[ top + 2 ].fibo;s[ top ].fibo = s[ top + 1 ].fibo + s[ top + 2 ].fibo; } // end if} // end if if ( 2 == s[ top ].ret ) {if ( 2 == s[ top ].ret ) { // second recursive call // second recursive call gotogoto l2; l2; }else if ( 3 == s[ top ].ret ) {}else if ( 3 == s[ top ].ret ) { goto goto l3;l3; } // end if} // end if

l4:l4: return s[ top ].fibo;return s[ top ].fibo; // all done// all done} // end nr_fibo } // end nr_fibo

Page 29: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

29

Simulate Recursion, fibo() Result

r_fibo( 0) = 0, calls = 1r_fibo( 0) = 0, calls = 1 r_fibo( 1) = 1, calls = 1 r_fibo( 1) = 1, calls = 1 r_fibo( 2) = 1, calls = 3 r_fibo( 2) = 1, calls = 3

r_fibo( 3) = 2, calls = 5r_fibo( 3) = 2, calls = 5 r_fibo( 4) = 3, calls = 9 r_fibo( 4) = 3, calls = 9 . . .. . . r_fibo(22) = 17711, calls = 57313r_fibo(22) = 17711, calls = 57313 r_fibo(23) = 28657, calls = 92735 r_fibo(23) = 28657, calls = 92735 r_fibo(24) = 46368, calls = 150049 r_fibo(24) = 46368, calls = 150049 r_fibo(25) = 75025, calls = 242785 r_fibo(25) = 75025, calls = 242785 r_fibo(26) = 121393, calls = 392835 r_fibo(26) = 121393, calls = 392835 r_fibo(27) = 196418, calls = 635621 r_fibo(27) = 196418, calls = 635621 r_fibo(28) = 317811, calls = 1028457 r_fibo(28) = 317811, calls = 1028457 r_fibo(29) = 514229, calls = 1664079 r_fibo(29) = 514229, calls = 1664079

nr_fibo( 0) = 0nr_fibo( 0) = 0nr_fibo( 1) = 1nr_fibo( 1) = 1nr_fibo( 2) = 1nr_fibo( 2) = 1nr_fibo( 3) = 2nr_fibo( 3) = 2nr_fibo( 4) = 3nr_fibo( 4) = 3

. . .. . .nr_fibo(22) = 17711nr_fibo(22) = 17711nr_fibo(23) = 28657nr_fibo(23) = 28657nr_fibo(24) = 46368nr_fibo(24) = 46368nr_fibo(25) = 75025nr_fibo(25) = 75025nr_fibo(26) = 121393nr_fibo(26) = 121393nr_fibo(27) = 196418nr_fibo(27) = 196418nr_fibo(28) = 317811nr_fibo(28) = 317811nr_fibo(29) = 514229nr_fibo(29) = 514229

Page 30: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

30

Simulating Return of fibo()

Must the computation of the continuation Must the computation of the continuation place be after the if-statement? Or can place be after the if-statement? Or can we relocate it into the Else-Clause?we relocate it into the Else-Clause?

That would lead to a partial simulation, That would lead to a partial simulation, in which only the case in which only the case arg > 1arg > 1 continues continues correctlycorrectly

Yet even cases for Yet even cases for arg <= 1arg <= 1 must compute must compute the right continuation via (unstructured) the right continuation via (unstructured) brute-force gotos:brute-force gotos:

if ( 2 == s[ top ].ret ) {if ( 2 == s[ top ].ret ) { // second recursive call // second recursive call goto l2;goto l2;

}else if ( 3 == s[ top ].ret ) {}else if ( 3 == s[ top ].ret ) { goto l3;goto l3;

} // end if} // end if

Page 31: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

31

Towers of hanoi() The game of the “Towers of Hanoi” is a game to The game of the “Towers of Hanoi” is a game to

move a stack of move a stack of nn discs, while obeying certain discs, while obeying certain rulesrules

All All nn discs are of different sizes, residing on discs are of different sizes, residing on top of one another, a smaller disc always over top of one another, a smaller disc always over a largera larger

The goal is to move the whole tower from The goal is to move the whole tower from startstart, , to the to the goalgoal position, using one additional position, using one additional bufferbuffer location location

But only moving 1 single disc at a timeBut only moving 1 single disc at a time

And never placing a larger disc on top of a And never placing a larger disc on top of a smallersmaller

During various times, any disc may be placed on During various times, any disc may be placed on the the startstart position, the position, the goalgoal, or the , or the bufferbuffer

Page 32: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

32

Towers of hanoi(), Recursive#include <iostream.h>#include <iostream.h>#define MAX … some small integer < 32#define MAX … some small integer < 32

void hanoi( int discs, char* start, char* goal, char* buff )void hanoi( int discs, char* start, char* goal, char* buff ){ // hanoi{ // hanoi

if ( discs > 0 ){if ( discs > 0 ){hanoi( discs-1, start, buff, goal );hanoi( discs-1, start, buff, goal );cout << "move disc " << discs << " from " << start << " to “cout << "move disc " << discs << " from " << start << " to “ << goal << endl;<< goal << endl;hanoi( discs-1, buff, goal, start );hanoi( discs-1, buff, goal, start ); } // end if} // end if

} // end hanoi} // end hanoi

int main()int main(){ // main{ // main

for ( int discs = 1; discs <= MAX; discs++ ) {for ( int discs = 1; discs <= MAX; discs++ ) {cout << ” hanoi for " << discs << " discs" << endl;cout << ” hanoi for " << discs << " discs" << endl;hanoi( discs, "start", "goal ", "buff " );hanoi( discs, "start", "goal ", "buff " );cout << endl;cout << endl; } // end for} // end for return 0;return 0;

} // end main} // end main

Page 33: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

33

Towers of hanoi(), Recursivemove disc 1 from start to goalmove disc 1 from start to goal < For 1 disc < For 1 disc

move disc 1 from start to buffmove disc 1 from start to buff < For 2 discs < For 2 discs move disc 2 from start to goal move disc 2 from start to goal move disc 1 from buff to goal move disc 1 from buff to goal

move disc 1 from start to goal move disc 1 from start to goal < For 3 discs < For 3 discs move disc 2 from start to buff move disc 2 from start to buff move disc 1 from goal to buff move disc 1 from goal to buff move disc 3 from start to goal move disc 3 from start to goal move disc 1 from buff to startmove disc 1 from buff to startmove disc 2 from buff to goal move disc 2 from buff to goal move disc 1 from start to goal move disc 1 from start to goal

move disc 1 from start to buff move disc 1 from start to buff < For 4 discs < For 4 discs move disc 2 from start to goal move disc 2 from start to goal move disc 1 from buff to goal move disc 1 from buff to goal move disc 3 from start to buff move disc 3 from start to buff move disc 1 from goal to startmove disc 1 from goal to startmove disc 2 from goal to buff move disc 2 from goal to buff move disc 1 from start to buff move disc 1 from start to buff move disc 4 from start to goal move disc 4 from start to goal move disc 1 from buff to goal move disc 1 from buff to goal move disc 2 from buff to startmove disc 2 from buff to startmove disc 1 from goal to startmove disc 1 from goal to startmove disc 3 from buff to goal move disc 3 from buff to goal move disc 1 from start to buff move disc 1 from start to buff move disc 2 from start to goal move disc 2 from start to goal move disc 1 from buff to goal move disc 1 from buff to goal

Page 34: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

34

Simulate Recursion, hanoi()void nr_hanoi( unsigned discs, char* start, char* goal, char* buff )void nr_hanoi( unsigned discs, char* start, char* goal, char* buff )

{ // nr_hanoi{ // nr_hanoistruct_h_type s[ MAX_STACK ]; unsigned top = 0;struct_h_type s[ MAX_STACK ]; unsigned top = 0;s[ top ].discs = discs;s[ top ].discs = discs;s[ top ].start = start;s[ top ].start = start;s[ top ].buff = buff;s[ top ].buff = buff;s[ top ].goal = goal;s[ top ].goal = goal;s[ top ].ret = 4;s[ top ].ret = 4;

l1:l1:if ( s[ top ].discs > 0 ) {if ( s[ top ].discs > 0 ) {top++;top++;s[ top ].discs = s[ top-1 ].discs - 1;s[ top ].discs = s[ top-1 ].discs - 1;s[ top ].start = s[ top-1 ].start;s[ top ].start = s[ top-1 ].start;s[ top ].buff = s[ top-1 ].goal;s[ top ].buff = s[ top-1 ].goal;s[ top ].goal = s[ top-1 ].buff;s[ top ].goal = s[ top-1 ].buff;s[ top ].ret = 2;s[ top ].ret = 2;goto l1;goto l1;

l2:l2:cout << "nr move disc “ << s[ top ].discs << “ from “cout << "nr move disc “ << s[ top ].discs << “ from “ << s[ top ].start << “ to “ << s[ top ].goal << endl;<< s[ top ].start << “ to “ << s[ top ].goal << endl;

top++;top++; s[ top ].discs = s[ top-1 ].discs - 1;s[ top ].discs = s[ top-1 ].discs - 1; s[ top ].start = s[ top-1 ].buff;s[ top ].start = s[ top-1 ].buff; s[ top ].buff = s[ top-1 ].start;s[ top ].buff = s[ top-1 ].start; s[ top ].goal = s[ top-1 ].goal;s[ top ].goal = s[ top-1 ].goal; s[ top ].ret = 3;s[ top ].ret = 3; goto l1;goto l1;} // end if} // end if

l3:l3:if ( 2 == s[ top ].ret ) {if ( 2 == s[ top ].ret ) { top--;top--; goto l2;goto l2;}else if ( 3 == s[ top ].ret ) {}else if ( 3 == s[ top ].ret ) { top--;top--; goto l3;goto l3;} // end if} // end if

} // end nr_hanoi} // end nr_hanoi

Page 35: 1 CS 410 / 510 Mastery in Programming Chapter 2 Recursion Herbert G. Mayer, PSU CS Status 7/6/2013 With improvements suggested by: Gaby Haddock, summer

35

References1.1. Douglas R. Hofstadter, “Gödel, Escher, Bach: Douglas R. Hofstadter, “Gödel, Escher, Bach:

an eternal golden braid”, Basic Books, 1999, an eternal golden braid”, Basic Books, 1999, ISBN 0465026567ISBN 0465026567

2.2. Ackermann function at NIST: Ackermann function at NIST: http://xlinux.nist.gov/dads/HTML/ackermann.hhttp://xlinux.nist.gov/dads/HTML/ackermann.htmltml

3.3. Herbert G Mayer: “Advanced C Programming on Herbert G Mayer: “Advanced C Programming on the IBM PC”, 1989, Windcrest, ISBN 0-8306-the IBM PC”, 1989, Windcrest, ISBN 0-8306-9163-49163-4

4.4. Non-recursive solution to Towers of Hanoi: Non-recursive solution to Towers of Hanoi: http://portal.acm.org/citation.cfm?id=948602http://portal.acm.org/citation.cfm?id=948602

5.5. Herbert G Mayer, Don Perkins, SIGLAN Herbert G Mayer, Don Perkins, SIGLAN Notices, 1984, non-recursive Towers of Hanoi Notices, 1984, non-recursive Towers of Hanoi Solution: http://dl.acm.org/citation.cfm?Solution: http://dl.acm.org/citation.cfm?id=948573id=948573