1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
use num::BigInt;
use crate::CollatzType;


pub type Collatz = CollatzType<BigInt>;


impl From<i64> for Collatz {
    fn from(i: i64) -> Collatz {
        if i <= 0 { panic!("Input must be a positive integer!") }
        let n = BigInt::from(i);
        Collatz { start: n }
    }
}

impl From<BigInt> for Collatz {
    fn from(n: BigInt) -> Collatz {
        if n <= BigInt::from(0) { panic!("Input must be a positive integer!") }
        Collatz { start: n }
    }
}

impl Iterator for Collatz {
    type Item = BigInt;
    fn next(&mut self) -> Option<Self::Item> {
        let n = self.start.clone();
        if n.clone() % 2 == BigInt::from(0) {
            self.start = n / 2;
            return Some(self.start.clone());
        } else if n.clone() == BigInt::from(1) {
            return None;
        } else {
            self.start = n * 3 + 1;
            return Some(self.start.clone());
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    #[should_panic]
    fn collatz_0() {
        let mut collatz = Collatz::from(0);
        assert_eq!(collatz.next(), None);
    }

    #[test]
    fn collatz_13() {
        let mut collatz = Collatz::from(13);
        assert_eq!(collatz.next(), Some(BigInt::from(40)));
        assert_eq!(collatz.next(), Some(BigInt::from(20)));
        assert_eq!(collatz.next(), Some(BigInt::from(10)));
        assert_eq!(collatz.next(), Some(BigInt::from(5)));
        assert_eq!(collatz.next(), Some(BigInt::from(16)));
        assert_eq!(collatz.next(), Some(BigInt::from(8)));
        assert_eq!(collatz.next(), Some(BigInt::from(4)));
        assert_eq!(collatz.next(), Some(BigInt::from(2)));
        assert_eq!(collatz.next(), Some(BigInt::from(1)));
        assert_eq!(collatz.next(), None);
    }
}