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
pub trait Divisors: Sized {
    fn divisors(self) -> impl Iterator<Item = Self>;
}

macro_rules! impl_uint {
    ( $($ty:ty)* ) => { $(
        impl Divisors for $ty {
            fn divisors(self) -> impl Iterator<Item = Self> {
                let n = self;
                std::iter::successors(
                    (n >= 1).then_some((1, true)),
                    move |&(i, asc)| {
                        if asc {
                            if let Some(j) = (i + 1..)
                                .take_while(|j| j * j <= n)
                                .find(|j| n % j == 0)
                            {
                                return Some((j, true));
                            } else if n / i != i {
                                return Some((i, false));
                            }
                        }
                        let j = (1..i).rev().find(|&j| n % j == 0)?;
                        Some((j, false))
                    },
                )
                .map(move |(i, asc)| if asc { i } else { n / i })
            }
        }
    )* };
}

impl_uint! { u8 u16 u32 u64 u128 usize }

#[test]
fn sanity_check() {
    assert!(0_u32.divisors().eq(None));

    for n in 1_u32..=10000 {
        let expected = (1..=n).filter(|i| n % i == 0);
        let actual = n.divisors();
        assert!(actual.eq(expected));
    }
}