E0507 lifetime may not live long enough

28 Views Asked by At

Goal: Create a function that returns an iterator for all combinations according to nCr.

For example, let n = 5 and let c = 3. The iterator should yield slices containing the following data.

0 1 2
0 1 3
0 1 4
0 2 3
0 2 4
0 3 4
1 2 3
1 2 4
1 3 4

To challenge myself, as I'm new to rust, I want to do it without allocating a new vector for every iteration. Instead, the iterator should modify a vector that it owns and always return a slice over the same vector. Yes, I know the values in the slice will change if the slice is improperly used after subsequent calls to next on the iterator.

/// Usage: 
/// Let's find all factors of 100. We have obtained all the prime factors earlier.
/// ```
/// let prime_factors = vec![2, 2, 5, 5]; // obtained earlier
/// let mut all_factors = new HashMap::<usize>();
/// all_factors.insert(1);
///
/// // now use every combination of prime factors to find all the factors
/// for c in 1..=prime_factors.len() { 
///     for indexes in combinations(prime_factors.len(), c) {
///         let mut factor = 1;
///         for index in indexes { 
///             factor *= prime_factors[index];
///         }
///         all_factors.insert(factor);
///     }
/// }
///
/// // all_factors now contains [1, 2, 4, 5, 10, 20, 50, 100]
/// ````
fn combinations<'a>(n: usize, c: usize) -> impl Iterator<Item = &'a [usize]> {
    struct State<'a> {
        n: usize,
        c: usize,
        indexes: Vec<usize>, // I think State should OWN this vector
        phantom: PhantomData<&'a ()>, // But I needed a field with a lifetime
    }

    impl<'a> State<'a> {
        fn new(n: usize, c: usize) -> State<'a> {
            State {
                n,
                c,
                indexes: (0..c).collect::<Vec<usize>>(),
                phantom: PhantomData,
            }
        }

        fn update(&mut self) -> bool {
            fn update(indexes: &mut Vec<usize>, at: usize, max: usize) -> bool {
                indexes[at] += 1;
                if indexes[at] == max {
                    if at == 0 {
                        return false;
                    }
                    if !update(indexes, at - 1, max - 1) {
                        return false;
                    }
                    indexes[at] = indexes[at - 1] + 1;
                }
                true
            }
            update(&mut self.indexes, self.c - 1, self.c)
        }
    }

    impl<'a> Iterator for State<'a> {
        type Item = &'a [usize];
        fn next(self: &mut State<'a>) -> Option<&'a [usize]> {
            if self.update() {
                Some(&self.indexes[..])
            } else {
                None
            }
        }
    }

    State::new(n, c)
}
0

There are 0 best solutions below