11//! Identify a cycle in an infinite sequence.
22
3+ /// Find the meeting point and lambda using Floyd's algorithm.
4+ /// Returns (`lambda`, `meeting_element`, `tortoise_steps`).
5+ fn floyd_find_cycle < T , FS > ( start : & T , successor : & FS ) -> ( usize , T , usize )
6+ where
7+ T : Clone + PartialEq ,
8+ FS : Fn ( T ) -> T ,
9+ {
10+ let mut tortoise = successor ( start. clone ( ) ) ;
11+ let mut hare = successor ( successor ( start. clone ( ) ) ) ;
12+ let mut tortoise_steps = 1 ;
13+ while tortoise != hare {
14+ ( tortoise, hare) = ( successor ( tortoise) , successor ( successor ( hare) ) ) ;
15+ tortoise_steps += 1 ;
16+ }
17+ // tortoise and hare met at position tortoise_steps
18+ let mut lam = 1 ;
19+ hare = successor ( tortoise. clone ( ) ) ;
20+ while tortoise != hare {
21+ ( hare, lam) = ( successor ( hare) , lam + 1 ) ;
22+ }
23+ ( lam, tortoise, tortoise_steps)
24+ }
25+
26+ /// Find the cycle using Brent's algorithm.
27+ /// Returns (`lambda`, `meeting_element`, `hare_steps`).
28+ fn brent_find_cycle < T , FS > ( start : & T , successor : & FS ) -> ( usize , T , usize )
29+ where
30+ T : Clone + PartialEq ,
31+ FS : Fn ( T ) -> T ,
32+ {
33+ let mut power = 1 ;
34+ let mut lam = 1 ;
35+ let mut tortoise = start. clone ( ) ;
36+ let mut hare = successor ( start. clone ( ) ) ;
37+ let mut hare_steps = 1 ;
38+ while tortoise != hare {
39+ if power == lam {
40+ ( tortoise, power, lam) = ( hare. clone ( ) , power * 2 , 0 ) ;
41+ }
42+ ( hare, lam) = ( successor ( hare) , lam + 1 ) ;
43+ hare_steps += 1 ;
44+ }
45+ ( lam, hare, hare_steps)
46+ }
47+
348/// Identify a cycle in an infinite sequence using Floyd's algorithm (partial version).
449/// Return the cycle size, an element in the cycle, and an upper bound on the index of
550/// the first element.
3176 T : Clone + PartialEq ,
3277 FS : Fn ( T ) -> T ,
3378{
34- let mut tortoise = successor ( start. clone ( ) ) ;
35- let mut hare = successor ( successor ( start. clone ( ) ) ) ;
36- let mut tortoise_steps = 1 ;
37- while tortoise != hare {
38- ( tortoise, hare) = ( successor ( tortoise) , successor ( successor ( hare) ) ) ;
39- tortoise_steps += 1 ;
40- }
41- // tortoise and hare met at position tortoise_steps
42- let mut lam = 1 ;
43- hare = successor ( tortoise. clone ( ) ) ;
44- while tortoise != hare {
45- ( hare, lam) = ( successor ( hare) , lam + 1 ) ;
46- }
79+ let ( lam, tortoise, tortoise_steps) = floyd_find_cycle ( & start, & successor) ;
4780 // Handle edge case where they meet at the start position (pure cycle, mu = 0)
4881 // In this case, tortoise_steps equals lam, and to satisfy mu_tilde < mu + lam,
4982 // we must return 0.
@@ -57,26 +90,20 @@ where
5790/// # Warning
5891///
5992/// If no cycle exist, this function loops forever.
93+ #[ allow( clippy:: needless_pass_by_value) ]
6094pub fn floyd < T , FS > ( start : T , successor : FS ) -> ( usize , T , usize )
6195where
6296 T : Clone + PartialEq ,
6397 FS : Fn ( T ) -> T ,
6498{
65- let mut tortoise = successor ( start. clone ( ) ) ;
66- let mut hare = successor ( successor ( start. clone ( ) ) ) ;
67- while tortoise != hare {
68- ( tortoise, hare) = ( successor ( tortoise) , successor ( successor ( hare) ) ) ;
69- }
99+ let ( lam, mut tortoise, _tortoise_steps) = floyd_find_cycle ( & start, & successor) ;
100+ // Find the exact mu
70101 let mut mu = 0 ;
71- tortoise = start;
102+ let mut hare = tortoise. clone ( ) ;
103+ tortoise = start. clone ( ) ;
72104 while tortoise != hare {
73105 ( tortoise, hare, mu) = ( successor ( tortoise) , successor ( hare) , mu + 1 ) ;
74106 }
75- let mut lam = 1 ;
76- hare = successor ( tortoise. clone ( ) ) ;
77- while tortoise != hare {
78- ( hare, lam) = ( successor ( hare) , lam + 1 ) ;
79- }
80107 ( lam, tortoise, mu)
81108}
82109
@@ -113,19 +140,7 @@ where
113140 T : Clone + PartialEq ,
114141 FS : Fn ( T ) -> T ,
115142{
116- let mut power = 1 ;
117- let mut lam = 1 ;
118- let mut tortoise = start. clone ( ) ;
119- let mut hare = successor ( start. clone ( ) ) ;
120- let mut hare_steps = 1 ;
121- while tortoise != hare {
122- if power == lam {
123- ( tortoise, power, lam) = ( hare. clone ( ) , power * 2 , 0 ) ;
124- }
125- ( hare, lam) = ( successor ( hare) , lam + 1 ) ;
126- hare_steps += 1 ;
127- }
128- // At this point, hare has taken hare_steps steps and met tortoise.
143+ let ( lam, hare, hare_steps) = brent_find_cycle ( & start, & successor) ;
129144 // Use hare_steps as the upper bound, as it represents where we detected the cycle.
130145 let mu_tilde = hare_steps;
131146 ( lam, hare, mu_tilde)
@@ -137,23 +152,17 @@ where
137152/// # Warning
138153///
139154/// If no cycle exist, this function loops forever.
155+ #[ allow( clippy:: needless_pass_by_value) ]
140156pub fn brent < T , FS > ( start : T , successor : FS ) -> ( usize , T , usize )
141157where
142158 T : Clone + PartialEq ,
143159 FS : Fn ( T ) -> T ,
144160{
145- let mut power = 1 ;
146- let mut lam = 1 ;
147- let mut tortoise = start. clone ( ) ;
148- let mut hare = successor ( start. clone ( ) ) ;
149- while tortoise != hare {
150- if power == lam {
151- ( tortoise, power, lam) = ( hare. clone ( ) , power * 2 , 0 ) ;
152- }
153- ( hare, lam) = ( successor ( hare) , lam + 1 ) ;
154- }
161+ let ( lam, _hare, _hare_steps) = brent_find_cycle ( & start, & successor) ;
162+ // Find the exact mu
155163 let mut mu = 0 ;
156- ( tortoise, hare) = ( start. clone ( ) , ( 0 ..lam) . fold ( start, |x, _| successor ( x) ) ) ;
164+ let mut tortoise = start. clone ( ) ;
165+ let mut hare = ( 0 ..lam) . fold ( start, |x, _| successor ( x) ) ;
157166 while tortoise != hare {
158167 ( tortoise, hare, mu) = ( successor ( tortoise) , successor ( hare) , mu + 1 ) ;
159168 }
0 commit comments