Function Recursion

Started by
13 comments, last by Stroppy Katamari 11 years ago

...snip...

The analogy you presented, the child can have more children, kind of confuses me. If I am using recursion, I am making another call to the method I am in, so does that not mean that I am simply going back and forth between 2 children?

The recursive function operates on each node, which calls the recursive function on all it's children, i.e:
if we

  void Func(Node N){
    for(int i=0;i<N.Children.Count;i++) Func(N.Children);
    return;
  }
which allows you to operate on an indeterminable number of children.

>>>


package mainPackage;

public class RecursionCoin {

	final static int toonie = 6;
	
	static int[] coin = {0,0,0,0};
	static int turns = 0;
	
	public static void main(String[] args) {
		for(int i = 0; i < 4; i++){
			coin = 0 + (int)(Math.random() * ((6 - 0) + 1));
		}
		checkCoins(coin, turns);
		System.out.println(turns);
	}

	private static void checkCoins(int[] coin, int turns2) {
		turns = turns2 + 1;
		
		for(int i = 0; i < 4; i++){
			if(coin != toonie){
				coin = 0 + (int)(Math.random() * ((6 - 0) + 1));
				return checkCoins(coin, turns); //Once this function returns succesfully, you know that you are done.
                                //returning here allows all your recursive functions to escape, instead of each doing potentially more work.
			}
		}
	}
}

Made a small change for doing unnecessary work.

That code has a side effect. You're returning a void method? What is the point of that. What you should do is say that once it returns successfully, you break out of the loop:


checkCoins:
for(int i = 0; i < 4; i++) {
  if(coin != toonie) {
    coin = (int) (Math.random() * ((6-0) + 1));
    return checkCoins(coin, turns);
    break checkCoins;
  }
}

This is a labeled break statment.

Once it returns successfully, you break out and avoid a side-effect of the method.

(Yes, I know it's an unimportant side effect that doesn't actually affect anything, however consistency smile.png!)

(I just want to point out that there are some non-elegant pieces of your code, such as using an int assigned to a random number to toonie. You could create a class with an state called isToonie


class Coin {
  bool isToonie = false;
}

and then have your code make more sense (instead of: if (coin != toonie), we get: if (coins[index].isToonie))).

Cheers smile.png!

I'm a game programmer and computer science ninja !

Here's my 2D RPG-Ish Platformer Programmed in Python + Pygame, with a Custom Level Editor and Rendering System!

Here's my Custom IDE / Debugger Programmed in Pure Python and Designed from the Ground Up for Programming Education!

Want to ask about Python, Flask, wxPython, Pygame, C++, HTML5, CSS3, Javascript, jQuery, C++, Vimscript, SFML 1.6 / 2.0, or anything else? Recruiting for a game development team and need a passionate programmer? Just want to talk about programming? Email me here:

hobohm.business@gmail.com

or Personal-Message me on here !

Advertisement

...snip...

The analogy you presented, the child can have more children, kind of confuses me. If I am using recursion, I am making another call to the method I am in, so does that not mean that I am simply going back and forth between 2 children?

The recursive function operates on each node, which calls the recursive function on all it's children, i.e:
if we

  void Func(Node N){
    for(int i=0;i<N.Children.Count;i++) Func(N.Children);
    return;
  }
which allows you to operate on an indeterminable number of children.

>


package mainPackage;

public class RecursionCoin {

	final static int toonie = 6;
	
	static int[] coin = {0,0,0,0};
	static int turns = 0;
	
	public static void main(String[] args) {
		for(int i = 0; i < 4; i++){
			coin = 0 + (int)(Math.random() * ((6 - 0) + 1));
		}
		checkCoins(coin, turns);
		System.out.println(turns);
	}

	private static void checkCoins(int[] coin, int turns2) {
		turns = turns2 + 1;
		
		for(int i = 0; i < 4; i++){
			if(coin != toonie){
				coin = 0 + (int)(Math.random() * ((6 - 0) + 1));
				return checkCoins(coin, turns); //Once this function returns succesfully, you know that you are done.
                                //returning here allows all your recursive functions to escape, instead of each doing potentially more work.
			}
		}
	}
}

Made a small change for doing unnecessary work.

That code has a side effect. You're returning a void method? What is the point of that. What you should do is say that once it returns successfully, you break out of the loop:


if (coin != toonie) {
  coin = 0 + (int) (Math.random() * ((6 - 0) + 1));
  checkCoins(coin, turns);
  break;
}

Once it returns successfully, you break out and avoid a side-effect of the method.

(Yes, I know it's an unimportant side effect that doesn't actually affect anything, however consistency smile.png!)

(I just want to point out that there are some non-elegant pieces of your code, such as using an int assigned to a random number to toonie. You could create a class with an state called isToonie


class Coin {
  bool isToonie = false;
}

and then have your code make more sense (instead of: if (coin != toonie), we get: if (coins[index].isToonie))).

Cheers smile.png!

Thanks for the pointers!
Fixed my code, works like a charm

Also, it's smarter to use loops for this, considering that it can overflow the stack (as mentioned by slicer4ever).

I'm a game programmer and computer science ninja !

Here's my 2D RPG-Ish Platformer Programmed in Python + Pygame, with a Custom Level Editor and Rendering System!

Here's my Custom IDE / Debugger Programmed in Pure Python and Designed from the Ground Up for Programming Education!

Want to ask about Python, Flask, wxPython, Pygame, C++, HTML5, CSS3, Javascript, jQuery, C++, Vimscript, SFML 1.6 / 2.0, or anything else? Recruiting for a game development team and need a passionate programmer? Just want to talk about programming? Email me here:

hobohm.business@gmail.com

or Personal-Message me on here !

I'll try and talk about why recursion is useful. The most obvious is that it can greatly simplify problems. For example, consider the following: what if you had a binary tree (not sorted), and you wanted to find out if a certain value is in that tree? The simplest code I can think of to do that is using recursion, not loops. I'll post some sample code that uses recursion to search a binary tree for a particular value. Notice it's pretty simple, short, and easy to follow and understand (hopefully). Now try seeing if you can write the equivalent using loops (in just 3 lines of code, like my recursive search... that should show you why recursion is nice):

 
// Just for reference, this is the kind of data structure I'm assuming
struct BinaryTree
{
  struct Node
  {
    Node* left;
    Node* right;
    int value;
  };
 
  Node root;
};
 
// Basically, this is a recursive depth first search
bool find(int value, const BinaryTree::Node* root)
{
  if (root == NULL) return false;
 
  if (root->value == value) return true;
 
  return find(value, root->left) || find(value, root->right);
}
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

Can someone just skim through my code, see if this makes sense?

The point of using recursion on something like this is usually being able to write readable, concise and safe code. Your code, unfortunately, is a bit of a mess due to how it uses shared state (the static variables outside the functions). When it does the recursive function call, that's pretty much a replacement for a goto. The result is uglier than a normal iterative solution, never mind a recursive one.

Here's a recursive solution without external state. (This is Scala code, but I'm hoping it's about as easy to read as pseudocode. I omitted some trivial code.)

// takes a collection of four coins as an argument, exchanges one non-toonie coin, returns the new set of four coins
def try_to_improve(Coins c): Coins = ...
 
// tests whether all coins in the collection are toonies
def all_toonies(Coins c): Boolean = ...
 
// recursive func
def toonie_recursive(Coins c, Int tries): Int =
   if (all_toonies(c))
      return tries
   else
      return toonie_recursive(try_to_improve(c), tries+1)
 
// initial call
total_tries = toonie_recursive(initial_coins, 1)

This topic is closed to new replies.

Advertisement