1struct CollatzSequence<T>
5where
6 T: num::Integer + Copy,
7{
8 next: T,
9}
10
11impl<T> CollatzSequence<T>
12where
13 T: num::Integer + Copy,
14{
15 fn new(number: T) -> CollatzSequence<T> {
17 CollatzSequence { next: number }
18 }
19}
20
21impl<T> Iterator for CollatzSequence<T>
22where
23 T: num::Integer + Copy,
24{
25 type Item = T;
26
27 fn next(&mut self) -> Option<Self::Item> {
28 if self.next <= T::one() {
29 return None;
30 }
31 self.next = if self.next % (T::one() + T::one()) == T::zero() {
32 self.next / (T::one() + T::one())
33 } else {
34 (T::one() + T::one() + T::one()) * self.next + T::one()
35 };
36 Some(self.next)
37 }
38}
39
40pub fn get_steps<T>(number: T) -> Vec<T>
47where
48 T: num::Integer + Copy,
49{
50 let c = CollatzSequence::new(number);
51 c.collect()
52}
53
54pub fn total_stopping_time<T>(number: T) -> usize
58where
59 T: num::Integer + Copy,
60{
61 let c = CollatzSequence::new(number);
62 c.count()
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[test]
70 fn test_count_steps() {
71 let numbers = [
72 0,
73 1,
74 2,
75 4,
76 9,
77 97,
78 871,
79 6171,
80 77_031,
81 837_799,
82 8_400_511,
83 931_386_509_544_713_451,
84 ];
85 let steps = [0, 0, 1, 2, 19, 118, 178, 261, 350, 524, 685, 2283];
86 for (i, n) in numbers.iter().enumerate() {
87 assert_eq!(steps[i], total_stopping_time::<u128>(*n));
88 assert_eq!(steps[i], get_steps(*n).len());
89 }
90 }
91
92 #[test]
93 fn test_get_steps() {
94 let steps = vec![
95 58, 29, 88, 44, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1,
96 ];
97 assert_eq!(steps, get_steps(19));
98
99 let steps = vec![
100 82, 41, 124, 62, 31, 94, 47, 142, 71, 214, 107, 322, 161, 484, 242, 121, 364, 182, 91,
101 274, 137, 412, 206, 103, 310, 155, 466, 233, 700, 350, 175, 526, 263, 790, 395, 1186,
102 593, 1780, 890, 445, 1336, 668, 334, 167, 502, 251, 754, 377, 1132, 566, 283, 850, 425,
103 1276, 638, 319, 958, 479, 1438, 719, 2158, 1079, 3238, 1619, 4858, 2429, 7288, 3644,
104 1822, 911, 2734, 1367, 4102, 2051, 6154, 3077, 9232, 4616, 2308, 1154, 577, 1732, 866,
105 433, 1300, 650, 325, 976, 488, 244, 122, 61, 184, 92, 46, 23, 70, 35, 106, 53, 160, 80,
106 40, 20, 10, 5, 16, 8, 4, 2, 1,
107 ];
108 assert_eq!(steps, get_steps(27));
109 }
110}