How to turn java for loops into recursion? [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have three for loops, and I wish to turn them into recursive method because I want to do this for any amount of for loops. I searched online, but nobody seems to have exactly what I need, for example this guy turns recursion into for loops
Turning a recursive function into a for loop?
Code:
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]);
}
}
}

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.

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!

Related

Why does insertion sort work only if we use while as an inner loop and doesn’t work for ” for loop”? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I was trying to attempt a insertion algorithm question. However, I had the following question.
I wanted to nderstand why most solutions online use a nested while loop instead of a nested for loop? I thought it might have to do something with time complexity, however, both have a O(n^2) complexity.
Below I have attached the two different solutions
public class InsertionSort {
// MY method
/*Function to sort array using insertion sort*/
// void sort(int arr[])
// {
// int n = arr.length;
// for (int i = 1; i < n; ++i) {
// if(arr[i] < arr[i-1]){
// for(int j = 0; j < i; j++){
// if(arr[i] < arr[j]){
// int temp = arr[j];
// arr[j] = arr[i];
// arr[i] = temp;
// }
// }
// }
// }
// }
// Online Solution
void sort(int arr[])
{
int n = arr.length;
for (int i = 1; i < n; ++i) {
int key = arr[i];
int j = i - 1;
/* Move elements of arr[0..i-1], that are
greater than key, to one position ahead
of their current position */
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
}
}
Usually, when developing algorithms, you choose a loop based on this:
If the number of iterations is known, use a for-loop.
If the number of iterations is not known, use a while-loop.
In Java, and other languages, you can implement the same thing using both loops. It doesn't matter if the number of iterations is known. However, it makes sense, it's more readable/logical:
... for a known starting value to a known limit do ...
... while a condition is true do ...
In pseudocode, which is a way to describe an algorithm independently of implementation-details, it's often done just like that (or similar):
for i = 0 to n do
...
while condition do
...
When you look at sort, you can see two loops: the outer for-loop and the inner while-loop.
The outer loop is a for-loop because i and n are known. Value n is known because it's given by the size of the array, which is a constant in this algorithm.
The inner loop is a while-loop because it's not known when the condition will fail, as it depends on an array-access. You don't know the values; if you would, then you could sort the array by hardcoding some swaps.

Calculating the factorial of every element in an integer array

I need to create a Method that has 2 parameters in Java, upperborder and lowerborder. This method must create an array from the number 2 to the number 10.
Then I must implement another method, that calculates the factorial for a given number.
Then I must implement a third method that calculates the factorial for every element in the created array and test all these methods in a TestClass.
I know how to do this, but apparently I'm making some kind of a mistake in my code and it gives me the StackOverflow exception. I read the code a couple of times, but I can't seem to quite understand where I'm wrong.
package fakultaetinarray;
public final class FakultaetinArray{
private int i;
private int[] a;
private int j;
public FakultaetinArray(){
System.out.println("Given array : ");
createArray(1, 9);
System.out.println("Factorial for every element : ");
FakinArray();
}
public int fakRe(int n){
if(n == 1){
return n;
}
return n * fakRe(n - 1);
}
public void createArray(int untergrenze, int obergrenze){
this.a = new int[obergrenze];
for(this.j = 1; j <= a.length; j++){
a[i] = j + 1;
System.out.println(a[i]);
}
}
public void FakinArray(){
a[0] = 2;
for(i = 1; i < a.length; i++){
int fak = fakRe(a[i]);
a[i] = fak;
System.out.println(fak);
}
}
}
The reason you're getting StackOverflowErrors is due to your recursive method not having a case when n == 0.
The reason that your values are coming in as 0 is due to how you're constructing your loop.
for(this.j = 1; j <= a.length; j++){
a[i] = j + 1;
System.out.println(a[i]);
}
It's unclear why you're using j here at all, and i is initialized to its default value of 0, so in all reality, you're only ever filling one element of your array with a positive value and all of the others are at zero.
You need to reconsider how your loops are constructed. I would strongly encourage you not to make them fields, but declare them as part of the loop construct instead.
if(n == 1){ is not a strong enough condition to block the recursion: n can go below 1. In your particular case, you have a situation where n is 0.
Consider unwinding the recursion to a simple loop in any case. As a rule of thumb, recursion is not good for O(N) stuff.

Better Selection Sort in Java [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
Firstly, can you tell me which piece of code is better of selection sort? Then if you know better ways for selection sort, can you please share?
Note: Please inspect the second code closer because it is more complex than it looks.
class SelectionSort {
public static void selectionSort(double[] list) {
for (int i = 0; i < list.length - 1; i++) {
double currentMin = list[i];
int currentMinIndex = i;
for (int j = i + 1; j < list.length; j++) {
if (currentMin > list[j]) {
currentMin = list[j];
currentMinIndex = j;
}
}
if (currentMinIndex != i) {
list[currentMinIndex] = list[i];
list[i] = currentMin;
}
}
}
}
.
class SelectionSort {
public static double[] selectionSort(double[] array) {
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < i; j++) {
if (array[j] > array[i]) {
double temp = array[j];
array[j] = array[i];
array[i] = temp;
}
}
}
}
}
Both methods will solve your problem but the second one it's clearly and I think it will be faster. Why? Because it has to make less actions to complete the problem: in the first one you have 2 loops (like in the second one), but also it has to make 2 ifs vs 1 if in the second one. I'm not really secure about that but, if the program have to make less actions, it will be faster (just an assumption).
Also, I think it will be faster because in the first one, you through all the j elements, some of them unnecesary (you have to make an extra if), and in the second one you just go through the elements that you need so it is more efficient too.
So, in conclusion, I think the best practice that you have to use it's the second one.
I expect it will helps you a bit!
Performance wise, both are similar, O(n2). The second code is a bit cleaner though.

Dynamically change the number of nested for loops

I don't know if this is a stupid question, but I need to dynamically change the number of for-loops without using recursion.
For example, if n=3, I need 3 nested for-loops.
for(int i=0; i<size; i++){
for(int j=0; j<size-1; j++){
for(int k=0; k<size-2; k++){
//do something
}
}
}
If n=5:
for(int i=0; i<size; i++){
for(int j=0; j<size-1; j++){
for(int k=0; k<size-2; k++){
for(int l=0; l<size-3; l++){
for(int m=0; m<size-4; m++){
//do something
}
}
}
}
}
Is there any way to achieve this without recursion?
Another question: what is the use of Multiple Dispatch in Java? I'm trying to code something in ONE METHOD, and it should run different events in different cases of the parameter. NO IF STATEMENTS / TERNARY OPERATORS / CASES.
NOTE: I can ONLY have one method (part of the problem), and cannot use recursion. Sorry.
Think about how many times you run through this loop. It looks like (size!) / (size - n)!:
int numLoops = 1;
for (int i = 0; i < n; i++) {
numLoops*= (size - i);
}
for (int i = 0; i < numLoops; i++) {
//do something
}
It depends what exactly you're trying to do. Recursion can always be replaced with iteration (see this post for examples using a Stack to store state).
But perhaps the modulo (%) operator could work here? i.e. Have a single loop that increments a variable (i) and then the other variables are calculated using modulo (i % 3 etc). You could use a Map to store the values of the variables indirectly, if there are a varying number of variables.
You have to create array of loop counters and increment it manually.
Quick and dirty example:
public static void nestedFors(int n, int size) {
assert n > size;
assert size > 0;
int[] i = new int[n];
int l = n - 1;
while(l >= 0) {
if(l == n - 1) {
System.out.println(Arrays.toString(i));
}
i[l]++;
if(i[l] == size - l) {
i[l] = 0;
l--;
} else if(l < n - 1) {
l++;
}
}
}
Replace System.out.println(Arrays.toString(i)) with your own code.
You can check it here: http://ideone.com/IKbDUV
It's a bit convoluted, but: here is a way to do it without recursion, in one function and without ifs.
public static void no_ifs_no_recursion(int n){
int[] helper = new int[n-1];
int[] pointers = new int[n]; //helper for printing the results
int totalsize = 1;
for (int loops = 2; loops <= n; loops++){
helper[n - loops] = totalsize;
totalsize*=loops;
}
for (int i=0; i<totalsize; i++){
int carry = i;
for (int loops = 0; loops < n-1; loops++){
pointers[loops] = carry/helper[loops];
carry = carry - (pointers[loops]*helper[loops]);
}
System.out.println(Arrays.toString(pointers));
//or do something else with `i` -> `pointers[0]`, `j` -> `pointers[1]`, `k` -> `pointers[2]` etc..
}
}
I think you need a backtracking algorithm.
But then you would replace your nested loops with recursion.
I don't want to post links here as seems moderators don't like that.
Look at "eight queens puzzle" (you can Google it), you will get my idea.
I know this idea works as I've posed this same question (which you have) to myself on many occasions, and I've applied it several times successfully.
Here is a small example (I changed it as the previous one was a bit complex).
public class Test001 {
public static void main(String[] args) {
loop(0, 5, 10);
}
/**
* max_level - the max count of nesting loops
* size - the size of the collection
*
* 0 - top most level
* level 1 - nested into 0
* level 2 - nested into 1
* ...
* and so on.
*/
private static void loop(int level, int max_level, int size){
if (level > max_level) return;
for (int i=0; i<size-level; i++){
System.out.println("Now at level: " + level + " counter = " + i);
loop(level + 1, max_level, size);
}
}
}
But this still uses recursion.

Recursive method to print array [duplicate]

This question already has answers here:
What is a StackOverflowError?
(16 answers)
Closed 6 years ago.
This is the method code:
public static void printMatrix(int[][] m, int i, int j) {
if (i == m.length ||j==m.length) {
System.out.println();
} else {
System.out.print("[" + m[i][j] + "]");
printMatrix(m, i, j++);
printMatrix(m, i++, j);
}
}
I don´t know why it just prints the first position of the array until a StackOverFlow error.
Thanks for the help.
You call 2 times the recursive function, but it keep calling itself with i and j..
printMatrix(m, i, j++); << use ++j
printMatrix(m, i++, j); << use ++i
Here is a possible solution for you
public static void printMatrix(int[][] m, int i, int j)
{
System.out.print("[" + m[i][j] + "]");
if (i == m.length && j == m.length)
{
return;
}
if (j == m.length)
{
j = 0;
++i;
printMatrix(m, i, j);
}
else
{
j++;
printMatrix(m, i, j);
}
}
non-recursive
public static void printMatrix(int[][] m)
{
for (int i = 0; i < m.length; i++)
for (int j = 0; j < m.length; j++)
System.out.print("[" + m[i][j] + "]");
}
If you're trying to print each element of the matrix once, then none of the solutions in the other answers [EDIT: I guess we're down to one answer now] is going to help. The most they will do is get rid of the stack overflow error, but the output is still not going to be close to what you need.
Assuming this is a homework assignment and you've been told to use recursion for some reason (in real life nobody would do that), you have to step back and think about this: just what do you want printMatrix(m,i,j) to do? Presumably, you want to print the m[i][j] element, and then call printMatrix to print the rest of the matrix. When you call printMatrix recursively to start the printing rest of the matrix, what do you want i and j to be? Probably, you want the same i and the next column, j+1, but not if j is at the end of the row. Then you want ... I'll let you think about that. But I don't think you want printMatrix to call itself twice. Instead, you want it to call itself only once (at most); you'll probably need an if statement that looks something like
if(something)
printMatrix(something);
else
printMatrix(something different);
but it will still call itself only once (since it will pick one or the other).
I'll mention one other thing: you're comparing i to the number of rows in the array (m.length), but you're also comparing j to the number of rows in the array. That's fine if you know this is a square matrix. But if you want to compare j to the number of columns, compare it to m[i].length, since m[i] is itself an array (that represents one row of the matrix).
The size of array 'm' will be constant through out the recursive calls. Whereas the value of of i and j will be changing and base condition will be only satisfied once that. So it infinitely enter the base condition was the same i and j. That is why i guess it keeps printing only one value and after sometime the stack overflows. i do not really view this as proper use of recursion. Correct me if i'm wrong. when using recursion a problem reduces size as function calls are made till it is broken into the smallest unit possible, which can be identified by the base condition or the breaking point. I don't see this happening here.
public class Printarray {
static int max= 2;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
int array[]={1,2,3};
print(array,0);
}
public static void print(int array[],int i)
{
System.out.println(array[i]);
if(i==Printarray.max)
{
Printarray.max--;
return;
}
else
{
print(array,i+1);
}
}
}
This works for 1D array, you can try this for 2D arrays and see if it works.
I hope it helps!
private static void print(int[][] mat, int i, int j) {
// TODO Auto-generated method stub
if(mat==null){
return;
}
if(i==mat.length || j==mat[0].length){
return;
}
System.out.print(mat[i][j]+" ");
if(j==mat[0].length-1){
System.out.println();
print(mat,i+1,0);
}
print(mat,i,j+1);
}

Categories

Resources