Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting an infinite loop in a recursive function (R)

Tags:

r

recursion

I have a test df:

testdf<-data.frame(x = seq(1,10), y= c(1, 1, 4, 3, 2, 6, 7, 4, 9, 10))

testdf

    x  y
1   1  1
2   2  1
3   3  4
4   4  3
5   5  2
6   6  6
7   7  7
8   8  4
9   9  9
10 10 10

I want to write a function that inputs a row number and "follows" the y value until it finds a row for which column x = column y.

get_acc_x<-function(rownum){
  if(testdf[rownum, 'x'] == testdf[rownum, 'y']){
    return(rownum)
  }else{
    get_acc_x(testdf[rownum, 'y'])
  }
} 

So, running get_acc_x(1) returns 1, get_acc_x(9) returns 9, get_acc_x(2) returns 1, get_acc_x(5) also returns 1, etc.

But, if I were to run this function on the number 8, it would get into an infinite loop, going back and forth between 3 and 4. What is the easiest way to detect an infinite loop in this situation? I want to keep track of past inputs so I can stop the function if the same input is used more than once, but I don't know how best to go about keeping track of the inputs.

like image 253
C_Z_ Avatar asked Oct 28 '25 07:10

C_Z_


1 Answers

You can pass in a parameter marking visited rows:

get_acc_x<-function(rownum, seen){
  if (seen[rownum]) {
    # Whatever you want to do, cycle detected
  }
  seen[rownum] <- T
  if(testdf[rownum, 'x'] == testdf[rownum, 'y']){
    return(rownum)
  }else{
    get_acc_x(testdf[rownum, 'y'], seen)
  }
} 

When calling, use get_acc_x(rownum, rep(F, nrow(df)) to pass in an all False param.

like image 178
zw324 Avatar answered Oct 31 '25 01:10

zw324