Think of a for loop as a little anonymous function that takes the loop index value as a parameter. In order to start the next iteration of the loop, the function can return a call to itself with a new value for the loop index parameter.
Like this:
Object loop(int i, Object data) {
if (i > 0) {
return loop(i - 1, evolve(data));
} else {
return data;
}
}
That's the same as this:
for ( ; i > 0; i--) {
data = evolve(data);
}
In some languages, particularly Scheme, and who knows maybe Java 8 or 9, the compiler is guaranteed to compile a recursive function such as the function loop above just the same as it compiles the for loop above.
In other languages, including the current and past versions of Java, nearly all compilers will make an executable that builds a big call stack. When the call stack is large it may even overflow the permitted size and crash the program.
Answer from minopret on Stack OverflowThink of a for loop as a little anonymous function that takes the loop index value as a parameter. In order to start the next iteration of the loop, the function can return a call to itself with a new value for the loop index parameter.
Like this:
Object loop(int i, Object data) {
if (i > 0) {
return loop(i - 1, evolve(data));
} else {
return data;
}
}
That's the same as this:
for ( ; i > 0; i--) {
data = evolve(data);
}
In some languages, particularly Scheme, and who knows maybe Java 8 or 9, the compiler is guaranteed to compile a recursive function such as the function loop above just the same as it compiles the for loop above.
In other languages, including the current and past versions of Java, nearly all compilers will make an executable that builds a big call stack. When the call stack is large it may even overflow the permitted size and crash the program.
Haters aside, let's do this! [1]
Given:
int x = 3;
for (int i = 0; i < x; i++) {
for (int j = 0; j < x; j++) {
for (int k = 0; k < x; k++){
list.add(array[i] + array[j] + array[k]);
}
}
}
Let's consider that each loop is it's own recursive function - as this makes the recurrence cases much easier! This is also the only "non-thinking" method I know of to turn the loops into recursion. The recursive depth will be limited to 3*x => i+j+k so it's "fairly safe" for a smallish[2] x.
In Java it requires a separate method for each loop to encode this structure. (In a language with higher-order functions these three functions might be abstractly combined .. but not in Java [7].)
void loopI(int i) {
if (i < x) {
loopJ(0); // "start j loop"
loopI(i++); // "next i loop" / recurrence case
}
// "end loop" / base case
}
void loopJ(int j) {
if (j < x) {
loopK(0);
loopJ(j++);
}
}
void loopK(int k) {
if (k < x) {
list.add(array[i] + array[j] + array[k]);
loopK(k++);
}
}
// do it!
loopI(0);
All of these could be combined into a single recursive function, but that makes handling the recurrence cases a bit tougher as "thinking" and additional conditionals (or mod expressions, perhaps) are required to advance the state.
Here is an example of a combined recursive function (this is incorrect when x is 0). Unlike the three method approach above, the stack depth will grow to x^3 => i*j*k. This will easily kill Java's recursion limits - even for smallish values of x- as Java [7] doesn't have tail-call optimization.
void loop(int i, int j, int k) {
list.add(array[i] + array[j] + array[k]);
// advance states
k++;
if (k == x) { k = 0; j++; }
if (j == x) { j = 0; i++; }
if (i == x) { i = 0; }
// terminate on all wrap-around
if (i == 0 && j == 0 && k == 0) { return; }
// recurse
loop(i, j, k);
}
[1] YMMV, for theoretical purposes only - I love recursion, but it's not suited for this case in Java.
[2] For some value of "smallish". See how deep your stack can go!
java - Recursion using for-loop - Stack Overflow
recursion - Java For Loop into Recursive function - Stack Overflow
java - Change For Loop to Recursive Method - Stack Overflow
for loop to recursion JAVA - Stack Overflow
Videos
Actually you should break the function down first:
A loop has a few parts:
the header, and processing before the loop. May declare some new variables
the condition, when to stop the loop.
the actual loop body. It changes some of the header's variables and/or the parameters passed in.
the tail; what happens after the loop and return result.
Or to write it out:
foo_iterative(params){
header
while(condition){
loop_body
}
return tail
}
Using these blocks to make a recursive call is pretty straightforward:
foo_recursive(params){
header
return foo_recursion(params, header_vars)
}
foo_recursion(params, header_vars){
if(!condition){
return tail
}
loop_body
return foo_recursion(params, modified_header_vars)
}
Et voilΓ ; a tail recursive version of any loop. breaks and continues in the loop body will still have to be replaced with return tail and return foo_recursion(params, modified_header_vars) as needed but that is simple enough.
Going the other way is more complicated; in part because there can be multiple recursive calls. This means that each time we pop a stack frame there can be multiple places where we need to continue. Also there may be variables that we need to save across the recursive call and the original parameters of the call.
We can use a switch to work around that:
bar_recurse(params){
if(baseCase){
finalize
return
}
body1
bar_recurse(mod_params)
body2
bar_recurse(mod_params)
body3
}
bar_iterative(params){
stack.push({init, params})
while(!stack.empty){
stackFrame = stack.pop()
switch(stackFrame.resumPoint){
case init:
if(baseCase){
finalize
break;
}
body1
stack.push({resum1, params, variables})
stack.push({init, modified_params})
break;
case resum1:
body2
stack.push({resum2, params, variables})
stack.push({init, modified_params})
break;
case resum2:
body3
break;
}
}
}
Following up on @ratchet freak's answer, I created this example of how the Fibonacci function can be rewritten to a while loop in Java. Note that There's a much simpler (and efficient) way to rewrite the Fibonacci with a while loop though.
class CallContext { //this class is similar to the stack frame
Object[] args;
List<Object> vars = new LinkedList<>();
int resumePoint = 0;
public CallContext(Object[] args) {
this.args = args;
}
}
static int fibonacci(int fibNumber) {
Deque<CallContext> callStack = new LinkedList<>();
callStack.add(new CallContext(new Object[]{fibNumber}));
Object lastReturn = null; //value of last object returned (when stack frame was dropped)
while (!callStack.isEmpty()) {
CallContext callContext = callStack.peekLast();
Object[] args = callContext.args;
//actual logic starts here
int arg = (int) args[0];
if (arg == 0 || arg == 1) {
lastReturn = arg;
callStack.removeLast();
} else {
switch (callContext.resumePoint) {
case 0: //calculate fib(n-1)
callStack.add(new CallContext(new Object[]{arg - 1}));
callContext.resumePoint++;
break;
case 1: //calculate fib(n-2)
callContext.vars.add(lastReturn); //fib1
callStack.add(new CallContext(new Object[]{arg - 2}));
callContext.resumePoint++;
break;
case 2: // fib(n-1) + fib(n-2)
callContext.vars.add(lastReturn); //fib2
lastReturn = (int) callContext.vars.get(0) + (int) callContext.vars.get(1);
callStack.removeLast();
break;
}
}
}
return (int) lastReturn;
}
Like so:
public class Recursive {
public void r(int i) {
if (i < 1024) {
i *= 2;
System.out.println("Count is: " + i);
r(i);
}
}
public static void main(String[] args) {
Recursive r = new Recursive();
r.r(1);
}
}
Take the loop of main and put it in its own function with an argument int i. In that function, rewrite the loop to
- If the loop condition is false (
i >= 1024), thenreturn - Else, recursive call with argument
i*2.
Call the function with argument 1 or 2, depending on which of your programs you're rewriting (they don't entirely match).
Googling "how to convert for loop to recursion," there's a similar answer here, and an article with an example here.
This is a pretty big hint but the basic idea is that your arguments store the current loop state.
for (int i = 1; i <= n; i++)
{
// ....
}
is equivalent to:
private static void PerformAction(int n)
{
if (n > 0)
{
// Do something
PerformAction(n - 1);
}
}
This is something you should be able to Google pretty easily, make sure you try finding the answer yourself before asking the community. I don't mind answering questions like this, but I've found that you don't really learn anything if you ask first and look later.
private static void printStars(int n)
{
if (n>0){
system.out.println("*");
printStars(n-1);
}
}
Have a look at your loops, i.e. how they are related to each other. As an example let's take the 1st and 2nd:
for (int a = 0; a < N; a++) {
for (int b = a + 1; b < N; b++) {
As you can see each loop uses 3 values/variables:
- the loop variable (
a,b), let's call itx - the maximum value
N - an initial value (
0,a + 1), let's call itstart
Thus both loops could be rewritten as
for (int x = start; x < N; x++ ) { ... }
Now put that into a method and add a condition for the recursion:
void runInnerLoop( int start, int N) {
for (int x = start; x < N; x++ ) {
runInnerLoop( x + 1, N );
}
}
Note that in your case you'd need to also pass the list of strings as a parameter and add a string to it, either before of after the recursion.
Also note that I didn't include any additional check whether to do the recursive call or not. That way you'd eventually end up with start == N but the loop condition would take take of that. Adding a condition like if( x < N - 1 ) would prevent an unnecessary recursive call at the cost of additional condition evaluation. Which option would be faster remains to be seen but since that's probably not really relevant I'd opt for the easier to read version.
However, since you're current learing recursion: keep in mind to always check whether the abort condition can be reached in all cases or not. Otherwise you'd run into StackOverflowError etc. - which could also happen if your N is too big in which case you'd need a different approach.
Edit:
I must admit that I overlooked a piece of information in your question, i.e. there is a limited recursion depth which you called M. Thus I'll expand my answer with that information and I'll also explain how to get the "lists" you want to print.
Basically handling the recursion depth is easy: you pass the current depth + 1 to each call as well as the maximum depth and before doing a recursive call you check for depth < maxDepth - if this is true you do a recursice call, if it is false you print the current branch (i.e. the "list" of integers).
Handling the lists isn't that hard but doing it efficiently requires some thought. Basically each iteration adds a new list, i.e. 0,1,2 and 0,2,3 are different lists.
If you'd use lists you'd have to pass the current list to the recursive call and inside the loop create a new list, add all the values of the top list to it and finally add the current loop variable to it (e.g. List<Integer> list = new ArrayList<>( topList ); list.add(x);).
However, you only need the lists in the deepst calls, i.e. when printing or collecting them. This means all those intermediate lists are a waste of time and memory. So instead you might want to use a Stack to track the current loop values, i.e. at the start of an iteration you push the current value to the stack and remove the top value at the end of the iteration. That way you can reuse the same stack and print only the current loop variables (or collect them into a new list for later use).
Here's the top example using recursion depth and a stack:
void runInnerLoop( int start, int N, int depth, int maxDepth, Stack<Integer> stack) {
for (int x = start; x < N; x++ ) {
stack.push( x ); //add the current value to the stack
if( depth < maxDepth ) { //max depth not reached, do another recursion
runInnerLoop( x + 1, N, depth + 1, maxDepth, stack );
} else {
System.out.println( stack ); //max depth reached, print now
}
stack.pop(); //remove the top value from the stack
}
}
The inital call for your first example (N=4, maxDepth=3) would look like this:
runInnerLoop( 0, 4, 1, 3, new Stack<>() );
Update 4
static List<List<Integer>> f(int init, int N, int depth, List<Integer> ls) {
List<List<Integer>> all = new ArrayList<>();
for(int i = init; i < N; i++) {
List<Integer> ls_ = new ArrayList<Integer>();
ls_.addAll(ls);
ls_.add(i);
if(depth == 0) {
all.add(ls_);
} else {
all.addAll(f(i + 1, N, depth-1, ls_));
}
}
return all;
}
Original
Without spoiling too much maybe this helps you:
for (int i = 0; i < 10; i++)
System.out.println(i);
is semantically the same as:
public static void f(final int i) {
if (i < 10) {
System.out.println(i);
For.f(i + 1);
}
}
You will also notice that:
while(i < 10) {
System.out.println(i);
i++;
}
is basically the same thing and can be translated to recursion the same way.
I wouldn't recommend coding like this but you can rewrite every for-loop to a recursive function this way. for loops don't consume as much stack space.
When you nest for loops you can translate them using the same algorithm:
for (int x = 0; x < 3; x++)
for (int y = 0; y < 3; y++)
System.out.println(x + "," + y);
becomes two functions f,g:
public static void f(final int x) {
if (x < 3) {
For.g(x, 0);
For.f(x + 1);
}
}
public static void g(final int x, final int y) {
if (y < 3) {
System.out.println(x + "," + y);
For.g(x, y + 1);
}
}
Update
To answer the comments:
It doesn't matter how many for-loops you have nested. Every for-loop can be rewritten as a recursive function. If you have N nested for-loops you can rewrite them to N recursive functions. The method is as follow:
If you have for(TYPE i = INIT; CONDITION; P-EXPRESSION) { CODE } you can translate it to:
function NAME(TYPE i) {
if(CONDITION) {
CODE
P-EXPRESSION
NAME(i); //this is the recursive call
}
}
NAME(INIT)
If you have nested for-loops the method is the same but you have to pass local variables as parameters.
for(int a = INIT_A; CONDITION_A; P-EXPRESSION_A) {
CODE_A
for(int b = INIT_B; CONDITION_B; P-EXPRESSION_B) {
CODE_B
//^- if you use a in this you have to pass a as a parameter
for(int c = INIT_C; CONDITION_C; P-EXPRESSION_C) {
CODE_C
//^- same deal
}
}
}
Becomes roughly (pseudo-code):
function f(int a) {
if(CONDITION_A) {
CODE_A
g(a, INIT_B);
P-EXPRESSION_A
f(a);
}
}
function g(int a, int b) {
if(CONDITION_B) {
CODE_B
h(a,b, INIT_C);
P-EXPRESSION_B
g(a, b);
}
}
function h(int a, int b, int c) {
if(CONDITION_C) {
CODE_C
P-EXPRESSION_C
h(a,b,c);
}
}
f(INIT_A)
Update 2
The direct 1:1 translation using the above method gives you:
public static List<String> f(int a, int N, List<String> stringList) {
if(a < N) {
g(a, a + 1, N, stringList);
f(a + 1, N, stringList);
}
return stringList;
}
public static List<String> g(int a, int b, int N, List<String> stringList) {
if(b < N) {
h(a, b, b+1, N, stringList);
g(a, b+1, N, stringList);
}
return stringList;
}
public static List<String> h(int a, int b, int c, int N, List<String> stringList) {
if(c < N) {
String str = " ( " + Integer.toString(a)
+ " , " + Integer.toString(b)
+ " , " + Integer.toString(c) +" ) ";
stringList.add(str);
h(a, b, c+1, N, stringList);
}
return stringList;
}
It's not beautiful/optimal code but it's a translation of each for-loop to a recursive function.
Update 3
A nicer translation would have the form:
h a b c n
|c < n = (a,b,c) : h a b (succ c) n
|otherwise = []
g a b n
|b < n = h a b (succ b) n ++ g a (succ b) n
|otherwise = []
f a n
|a < n = g a (succ a) n ++ f (succ a) n
|otherwise = []
main = print $ f 0 4
but this would translate to java as:
public static List<String> f(int a, int N) {
if(a < N) {
List<String> ls = new ArrayList<String>();
ls.addAll(g(a, a + 1, N));
ls.addAll(f(a + 1, N));
return ls;
}
return new ArrayList<String>();
}
public static List<String> g(int a, int b, int N) {
if(b < N) {
List<String> ls = new ArrayList<String>();
ls.addAll(h(a,b,b+1,N));
ls.addAll(g(a,b+1,N));
return ls;
}
return new ArrayList<String>();
}
public static List<String> h(int a, int b, int c, int N) {
if(c < N) {
String str = " ( " + Integer.toString(a)
+ " , " + Integer.toString(b)
+ " , " + Integer.toString(c) +" ) ";
List<String> ls = new ArrayList<String>();
ls.add(str);
ls.addAll(h(a,b,c+1,N));
return ls;
}
return new ArrayList<String>();
}
Which is not efficient Java :).
can Someone help me convert this iterative function into a recursive function?
public int getMax(int [] A, int i, int j){
int max = A[i];
for (int k = i+1; k <=j ; k++) {
if(A[k]>max){
max = A[k];
}
}
return max;
}
I do not really understand recursion. I know the function will call itself at some point, but i'm pretty confused still.
Your problem is not in the part you posted.
I added dummy implementations for all the classes and methods used in your method, and it runs quite fine, stopping at level 6.
package de.fencing_game.paul.examples;
import java.util.*;
public class RecursionAndLoop {
private static class Move {
private String id;
public Move(String type) {
this.id = type;
}
public String toString(){
return "Move(" + id + ")";
}
}
private static class GameState {
private static int nextID;
private int id;
GameState() {
this.id = nextID++;
}
public GameState getNewInstance(Move move) {
return new GameState();
}
public int getPossibleMoveCount(int index) {
return 5;
}
public Vector<Move> getPossibleMoves(int index) {
Vector<Move> v = new Vector<Move>();
for(int i = 0; i < 5; i++) {
v.add(new Move(index + "Γ" + i));
}
return v;
}
public int getMarkCount(int index) {
return 20 + index;
}
public String toString() {
return "GameState[" + id + "]";
}
}
private static class Node {
private GameState state;
private Move move;
private List<Node> children;
private Node parent;
private int score;
public Node(GameState s, Move m) {
this.children = new ArrayList<Node>();
this.state = s;
this.move = m;
}
public void addChild(Node child) {
children.add(child);
}
public void setParent(Node node) {
parent = node;
}
public void setScore(int neu) {
this.score = neu;
}
public int getDepth() {
if(parent == null) {
return 0;
}
return 1 + parent.getDepth();
}
/**
* prints a simple tree view of this ZipNode and its descendants
* on {@link System.out}.
* @param prefix a prefix string to add before all lines.
* @param self a prefix string to add before the line of this node
* itself (after the general prefix).
* @param sub a prefix string to add before the line of all subnodes
* of this node (after the general prefix).
*/
private void printTree(String prefix,
String self,
String sub) {
System.out.println(prefix + self + state + " - " + move +
" - " + score);
String subPrefix = prefix + sub;
// the prefix strings for the next level.
String nextSelf = " ββ ";
String nextSub = " β ";
Iterator<Node> iterator =
this.children.iterator();
while(iterator.hasNext()) {
Node child = iterator.next();
if(!iterator.hasNext() ) {
// last item, without the "|"
nextSelf = " ββ ";
nextSub = " ";
}
child.printTree(subPrefix, nextSelf, nextSub);
}
}
}
int switchIndex(int index) {
return index + 1;
}
private void makeTree(GameState prevState, Vector<Move> moves, Node parentNode, int index, int depthLimit) {
if(prevState.getPossibleMoveCount(index) != 0){
for(int i = 0; i < moves.size(); i++){
Move thisMove = moves.get(i);
GameState newState = prevState.getNewInstance(thisMove);
Node child = new Node(newState, thisMove);
parentNode.addChild(child);
child.setParent(parentNode);
if((child.getDepth() + 1) < depthLimit){
int newIndex = switchIndex(index);
Vector<Move> newMoves = newState.getPossibleMoves(newIndex);
makeTree(newState, newMoves, child, newIndex, depthLimit);
}else{
child.setScore(newState.getMarkCount(index));
}
}
}
}
public static void main(String[] params) {
GameState start = new GameState();
Vector<Move> m = new Vector<Move>();
m.add(new Move("start"));
Node root = new Node(start, null);
int index = 7;
int depthLimit = 6;
new RecursionAndLoop().makeTree(start, m, root, index, depthLimit);
root.printTree("", " ", "");
}
}
(I changed a bit to generic types to avoid compiler warnings.)
Here is the output for depthLimit=4:
GameState[0] - null - 0
ββ GameState[1] - Move(start) - 0
ββ GameState[2] - Move(8Γ0) - 0
β ββ GameState[3] - Move(9Γ0) - 29
β ββ GameState[4] - Move(9Γ1) - 29
β ββ GameState[5] - Move(9Γ2) - 29
β ββ GameState[6] - Move(9Γ3) - 29
β ββ GameState[7] - Move(9Γ4) - 29
ββ GameState[8] - Move(8Γ1) - 0
β ββ GameState[9] - Move(9Γ0) - 29
β ββ GameState[10] - Move(9Γ1) - 29
β ββ GameState[11] - Move(9Γ2) - 29
β ββ GameState[12] - Move(9Γ3) - 29
β ββ GameState[13] - Move(9Γ4) - 29
ββ GameState[14] - Move(8Γ2) - 0
β ββ GameState[15] - Move(9Γ0) - 29
β ββ GameState[16] - Move(9Γ1) - 29
β ββ GameState[17] - Move(9Γ2) - 29
β ββ GameState[18] - Move(9Γ3) - 29
β ββ GameState[19] - Move(9Γ4) - 29
ββ GameState[20] - Move(8Γ3) - 0
β ββ GameState[21] - Move(9Γ0) - 29
β ββ GameState[22] - Move(9Γ1) - 29
β ββ GameState[23] - Move(9Γ2) - 29
β ββ GameState[24] - Move(9Γ3) - 29
β ββ GameState[25] - Move(9Γ4) - 29
ββ GameState[26] - Move(8Γ4) - 0
ββ GameState[27] - Move(9Γ0) - 29
ββ GameState[28] - Move(9Γ1) - 29
ββ GameState[29] - Move(9Γ2) - 29
ββ GameState[30] - Move(9Γ3) - 29
ββ GameState[31] - Move(9Γ4) - 29
When you call
makeTree(newState, newMoves, child, newIndex, depth);
inside of your if statement where are you expecting depth to come from? It looks like you're passing in depth to the makeTree routine, yet expecting it to be the depth of the current node (this.depth maybe?)