Printing a value from the given function, not the whole output

fn set_product<T>(items: &[T]) -> impl Iterator<Item = Vec<&T>> {
    (1..=items.len()).flat_map(|n| { std::iter::repeat(items.iter()).take(n).multi_cartesian_product()
    })
}

fn main() {
    for digits  in set_product(&["a", "b", "c", "d", "e"]) {
        println!("{:?}", digits);
    }
["a"]
["b"]
["c"]
["d"]
["e"]
["a", "a"]
["a", "b"]
["a", "c"]
["a", "d"]
["a", "e"]
["b", "a"]
["b", "b"]
["b", "c"]
["b", "d"]
["b", "e"]

...
...

Print this sequence from the above function?

Sure:

fn get_nth<T>(items: &[T], num: u128) -> Vec<&T> {
    let n = items.len() as u128;

    let mut output_len = 1;
    let mut current_len_combinations = n;
    let mut skip = 0;
    
    while skip + current_len_combinations <= num {
        skip += current_len_combinations;
        current_len_combinations *= n;
        output_len += 1;
    }
    
    let mut output = Vec::with_capacity(output_len);
    let mut num = num - skip;
    for _ in 0..output_len {
        output.push(&items[(num % n) as usize]);
        num = num / n;
    }
    
    output.reverse();
    output
}

fn main() {
    println!("{:?}", get_nth(&["a", "b", "c", "d", "e", "f"], 1366631));
}
["d", "e", "a", "d", "b", "e", "e", "f"]

It counts how many outputs of a shorter length we have to skip. Here's what happens if you remove it:

fn get_nth<T>(items: &[T], num: u128, output_len: usize) -> Vec<&T> {
    let n = items.len() as u128;
    
    let mut output = Vec::with_capacity(output_len);
    let mut num = num;
    for _ in 0..output_len {
        output.push(&items[(num % n) as usize]);
        num = num / n;
    }
    
    output.reverse();
    output
}

fn main() {
    for i in 0..20 {
        println!("{:?}", get_nth(&["a", "b", "c"], i, 4));
    }
}
["a", "a", "a", "a"]
["a", "a", "a", "b"]
["a", "a", "a", "c"]
["a", "a", "b", "a"]
["a", "a", "b", "b"]
["a", "a", "b", "c"]
["a", "a", "c", "a"]
["a", "a", "c", "b"]
["a", "a", "c", "c"]
["a", "b", "a", "a"]
["a", "b", "a", "b"]
["a", "b", "a", "c"]
["a", "b", "b", "a"]
["a", "b", "b", "b"]
["a", "b", "b", "c"]
["a", "b", "c", "a"]
["a", "b", "c", "b"]
["a", "b", "c", "c"]
["a", "c", "a", "a"]
["a", "c", "a", "b"]

Thank you.

This is an example of bijective numeration. You can actually drop the first loop if you aren't picky about the capacity being exact:

fn get_nth<T>(items: &[T], mut num: u128) -> Vec<&T> {
    num += 1;
    let base = items.len() as u128;
    let mut output = Vec::new();
    while num != 0 {
        let digit = num.wrapping_sub(1) % base + 1;
        output.push(&items[(digit - 1) as usize]);
        num = (num - digit) / base;
    }
    output.reverse();
    output
}

(The capacity issue could be corrected once u128::log() is stabilized; the Wikipedia page lists the formula for the digit count.)

1 Like