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?