Why can't I increment a variable like this?

Here is the more idiomatic version of next_permutation

fn next_permutation<T: PartialOrd + Copy>(permutation: &[T]) -> Option<Vec<T>> {
    use std::convert::TryFrom;
    
    for (i, i_val) in permutation.windows(2).enumerate().rev() {
        let [i_val, i_next] = <[T; 2]>::try_from(i_val).expect("Should Work");

        if i_val >= i_next {
            continue;
        }

        for (j, &j_val) in permutation.iter().enumerate().rev() {
            if j_val > i_val {
                let mut result = permutation.to_vec();

                result.swap(i, j);
                result[(i + 1)..].reverse();

                return Some(result);
            }
        }
    }

    None
}

And if you want it as a single iterator you have this monstrosity

fn next_permutation<T: PartialOrd + Copy>(permutation: &[T]) -> Option<Vec<T>> {
    use std::convert::TryFrom;
    // These renamings are for clarity
    use std::result::Result::{Err as Found, Ok as Continue};

    permutation
        .windows(2)
        .enumerate()
        .rev()
        .map(|(i, i_val)| (i, <[T; 2]>::try_from(i_val).expect("Should Work")))
        .filter(|(_, [i_val, i_next])| i_val < i_next)
        .try_fold((), |(), (i, [i_val, _])| {
            permutation
                .iter()
                .enumerate()
                .rev()
                .try_fold((), |(), (j, &j_val)| {
                    if j_val > i_val {
                        let mut result = permutation.to_vec();

                        result.swap(i, j);
                        result[(i + 1)..].reverse();

                        Found(result) // Err == Found means early return from try_fold
                    } else {
                        Continue(())
                    }
                })
        })
        .err() // Err == Found
}
4 Likes