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;
}
}
}
Answer from ratchet freak on Stack ExchangeActually 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;
}
replace for loop with recursive function for
Explanation for the given example for Replace Loops with Recursion
freeCodeCamp Challenge Guide: Replace Loops using Recursion - Guide - The freeCodeCamp Forum
Replace loop using recursion
Videos
If you can accomplish a task without recursion its a good idea to solve it that way. If you would like to learn about recursion check out some problems like factorial or Fibonacci. These also have iterative solutions but lend themselves much more to recursion than the problem you have here. In this case it is very clear what your algorithm is doing and recursion would make it needlessly harder to understand. Here is one improvement you could make however
for (int e = 0; e < length; e++)
{
key[4] = letters[e];
for (int d = 0; d < length; d++)
{
key[3] = letters[d];
for (int c = 0; c < length; c++)
{
key[2] = letters[c];
for (int b = 0; b < length; b++)
{
key[1] = letters[b];
for (int a = 1; a < length; a++)
{
key[0] = letters[a];
if (strcmp(crypt(key, salt), hash) == 0)
{
printf("%s\n", key);
return 0;
}
}
}
}
}
}
Although I don't disagree with everyone who has discouraged you from using recursion in this example, I wanted to write it recursively since I think it's a reasonable question.
Here's my attempt at writing it recursively. By doing this, I only need to write the loop once, since the outer loop is handled by the recursion. I've taken some liberties so it isn't exactly equivalent to your code, but I think in principle it is the same (testing all the combinations against hash) and shows the basic idea of how you could write this recursively. I'll assume you have a way of knowing the strcmp check is safe.
int recur(int cur, int klength, char *key, char *letters, int length, char *salt, char *hash)
{
if (cur == klength)
{
if (strcmp(crypt(key, salt), hash))
{
return 1;
}
else
{
return 0;
}
}
else
{
for (int i = 0; i < length; i++)
{
key[cur] = letters[i];
int j = recur(cur+1, klength, key, letters, length, salt, hash);
if (!j)
{
return 0;
}
}
return 1;
}
}
I would then call this with
recur(5, 0, ...)
to do the 5 loops you wrote. This isn't very elegant, but I think it's clear why this might be more elegant if you expanded your key to require 10 loops (and why it would be terrible for the stack at 10000 loops).
Having said that, my first thought looking at your code wasn't "recursion" it was "those outer loops look pretty similar, so I'd like to get rid of some of them." My code below isn't pretty (hey, it's late at night!), but I think in principle this would be a better approach if you think you might need to increase the number of characters you're testing to 10 (or 10000). What I'm trying to do is maintain an integer equivalent to key in idx. If I increment idx[0] and it is == length I know I need to reset idx[0] = 0 and try incrementing idx[1], etc. Every time I change idx[i] I make an equivalent change to key[i]. Every time I have a new permutation of idx/key, I do your strcmp test to see if I've found the correct one.
int ksize = 5;
int idx[ksize];
for (int i = 0; i < ksize; ++i)
{
idx[i] = 0;
key[i] = letters[0];
}
for (int done = 0; !done; )
{
if (strcmp(crypt(key, salt), hash) == 0)
{
printf("%s\n", key);
return 0;
}
for (int i = 0; ; i++)
{
if (++idx[i] == length)
{
idx[i] = 0;
}
key[i] = letters[idx[i]];
if (idx[i]) // We incremented idx[i] and it wasn't reset to 0, so this is a new combination to try
{
break;
}
else if (i == ksize-1) // We incremented idx[ksize-1] and it was reset to 0, so we've tried all possibilities without returning
{
done++;
break;
}
}
}
function operation() {
console.log("testing");
}
function repeat(operation, num) {
if (num === 0) return;
operation();
repeat(operation, num-1);
}
//repeat(operation, 10);
module.exports = repeat
Loops are iterative by nature. Recursive approach does not really fit into this situation. Anyhow, here you go. But use it only for fun, never for real :)
function repeat(func,maxruns,run){
if(run>=maxruns){
return;
}
func();
repeat(func,maxruns,(run||0)+1);
}
repeat(operation,10);
I favor recursive solutions when:
The implementation of the recursion is much simpler than the iterative solution, usually because it exploits a structural aspect of the problem in a way that the iterative approach cannot
I can be reasonably assured that the depth of the recursion will not cause a stack overflow, assuming we're talking about a language that implements recursion this way
Condition 1 doesn't seem to be the case here. The iterative solution is about the same level of complexity, so I'd stick with the iterative route.
If performance matters, then benchmark both and choose on a rational basis. If not, then choose based on complexity, with concern for possible stack overflow.
There is a guideline from the classic book The Elements of Programming Style (by Kernighan and Plauger) that algorithm should follow data structure. That is, recursive structures are often processed more clearly with recursive algorithms.
Assuming you have your list set up so that tab[0] is the list of the first strings to print, tab[1] the following strings, etc., you can use recursion as follows:
void print_rec(List<String>[] tab, int depth, String str) {
int maxdepth = tab.length - 1;
for (int i = 0; i < tab[depth].size(); i++) { // number of strings at this depth
if (depth == maxdepth) {
System.out.println(str + tab[depth].get(i)); // print line
// no more lists to go through, print the line
} else {
print_rec(tab, depth + 1, str + tab[depth].get(i) + " ");
// add next entry at this level to str and recurse
}
}
// done with this depth, go back up one
}
void printAll(List<Strings>[] tab) {
print_rec(tab, 0, "");
}
This covers all the entries exactly like nested loops.
Here is a solution. It's a modification of my answer to your other post: how to use recursion for nested 'for' loops.
public static void iterate(Object[] previousValues, List<Object>[] tabs) {
if (tabs.length == 0) {
System.out.println(Arrays.toString(previousValues));
}
else {
final Object[] values = new Object[previousValues.length + 1];
for (int i = 0; i < previousValues.length; i++) {
values[i] = previousValues[i];
}
final List<Object>[] nextTabs = new List[tabs.length - 1];
for (int i = 0; i < nextTabs.length; i++) {
nextTabs[i] = tabs[i + 1];
}
for (Object o : tabs[0]) {
values[values.length - 1] = o;
iterate(values, nextTabs);
}
}
}
public static void iterate(List<Object>[] tabs) {
iterate(new Object[0], tabs);
}
public static void main(String[] args) {
final List<String> firstTab = new ArrayList<>();
firstTab.add("England");
final List<String> secondTab = new ArrayList<>();
secondTab.add("London");
secondTab.add("Liverpool");
final List<String> thirdTab = new ArrayList<>();
thirdTab.add("DG300");
thirdTab.add("SS500");
iterate(new List[]{firstTab, secondTab, thirdTab});
}