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 65 66 67 68 69 70 71 72 73
use num_bigint::{BigUint}; use num_traits::{Zero, One}; use std::ops::{Add, Mul, Div}; use num_bigint::ToBigUint; pub struct BigCollatz { curr: BigUint, done: bool, pub start: BigUint, pub steps: u32, } pub struct CollatzStep { pub step: u32, pub curr: BigUint, } impl BigCollatz { pub fn new(ini: BigUint) -> BigCollatz { BigCollatz { start: ini.clone(), curr: ini.clone(), steps: 0, done: false, } } } impl Iterator for BigCollatz { type Item = CollatzStep; fn next(&mut self) -> Option<CollatzStep> { if self.done { return None; }; let one: BigUint = BigUint::one(); let zero: BigUint = BigUint::zero(); let two: BigUint = BigUint::from(2u32); let three: BigUint = BigUint::from(3u32); let curr = &self.curr; let result = curr.clone(); if curr % &two == zero { self.curr = curr.div(&two); } else { self.curr = curr.mul(&three).add(&one); } if self.curr <= one { self.done = true } self.steps += 1; Some(CollatzStep { step: self.steps, curr: result, }) } } #[cfg(test)] mod tests { use super::*; #[test] fn it_works() { let c = BigCollatz::new(100.to_biguint().unwrap()); for x in c { println!("n:{}, step:{}", x.curr, x.step); assert_eq!(x.curr > BigUint::one(), true); } } }