I was going through Wikipedia implementation of Cycle detection using Tortoise-and-Hare algorithm. Using Ruby language, this is what I implemented:
def tortoise_and_hare(sequence) tortoise = 1 hare = 2 while sequence[tortoise] != sequence[hare] tortoise += 1 hare += 2 end # Find start index of first repetition idx = 0 tortoise = 0 while sequence[tortoise] != sequence[hare] tortoise += 1 hare += 1 idx += 1 end # Find length of cycle starting from index idx length = 1 hare = tortoise + 1 while sequence[tortoise] != sequence[hare] hare += 1 length += 1 end [idx, length] end sequence = [2, 0, 6, 3, 1, 6, 3, 1, 6, 3, 1] idx, length = tortoise_and_hare(sequence) p sequence[idx, length]
This is working correctly and returns [6, 3, 1]
. Now,
- If I trim the sequence to
[2, 0, 6, 3, 1, 6, 3, 1]
, it returns empty set. - I can see the problem is in second loop. If cycle has
repeating character, algorithm returns incorrect answer. Example,
[2, 0, 6, 3, 1, 6, 6, 3, 1, 6, 6, 3, 1, 6]
returns[6, 3, 1]
, but should be[6, 3, 1, 6]
. I can see the problem is in third loop.
So I guess my questions are:
- Is the algorithm posted on Wikipedia standard?
- Is my second case incorrect? I know cycle detection means infinitesimally long sequence which my exam is not, but it still has a cycle.
- If the case is correct, what can we do to improve the algorithm and solve the 2 issues I pointed out above?
I tried modifying second loop for first problem (trimming the sequence small enough for the algorithm to fail) and it worked:
# Find start index of first repetition idx = 0 tortoise = 0 while sequence[tortoise] != sequence[hare] tortoise += 1 hare += 1 hare = tortoise if hare > sequence.length - 1 idx += 1 end
- Does it look wrong or may fail in some case?
- What can we do for second problem (repeating characters)?
Although I cam up with another elegant Regex based solution, I still would like to learn more about above algorithm.
Regex solution for curious: /(?<cycle>(\d+\s)+(\d+))\s\k<cycle>/
Edit: I understood why it is impossible for it to detect repeated characters. But is there any other algorithm that may help in this situation?