[][src]Struct permutator::XPermutationIterator

pub struct XPermutationIterator<'a, F, T> where
    F: FnMut(&[&T]) -> bool,
    T: 'a, 
{ /* fields omitted */ }

A lexicographic ordered permutation based on "Algoritm X" published by Donald E. Knuth. page 20.

If order is not important, consider using heap permutation struct instead. This struct is a bit slower (about 10%) than heap permutation in uncontroll test environment.

The algorithm work by simulate tree traversal where some branch can be skip altogether. This is archive by provided t function that take slice of partial result as parameter. If the partial result needed to be skip, return false. Otherwise, return true and the algorithm will call this function again when the branch is descended deeper. For example: First call to t may contain [1]. If t return true, it will be called again with [1, 2]. If it return true, and there's leaf node, cb will be called with [1, 2]. On the other hand, if t is called with [1, 3] and it return false, it won't call the callback. If t is called with [4] and it return false, it won't try to traverse deeper even if there're [4, 5], or [4, 6]. It will skip altogether and call t with [7]. The process goes on until every branch is traversed.

Example

Get all lexicalgraphic ordered permutation

use permutator::XPermutationIterator;
 
let data = vec![1, 2, 3, 4];
let mut counter = 0;

XPermutationIterator::new(&data, |_| true).for_each(|p| {
    println!("{:?}", p);
    counter += 1;
});

assert_eq!(factorial(data.len()), counter);

Skip all permutation that has 1 in first element.

use permutator::XPermutationIterator;
 
let data : Vec<u8> = vec![1, 2, 3, 4];
let mut counter = 0;

XPermutationIterator::new(&data, |f| {
    *f[0] != 1u8 // filter all permutation that start with 1
}).for_each(|p| {
    println!("{:?}", p);
    counter += 1;
});

assert_eq!(factorial(data.len()) - factorial(data.len() - 1), counter);

Multi-threads permutation example

use permutator::XpermutationIterator;
use std::time::{Instant};
let data : Vec<usize> = (0..4).map(|num| num).collect();
let threads = 2;
let chunk = data.len() / threads;
let (tx, rx) = mpsc::channel();

for i in 0..threads {
    let start = chunk * i;
    let end = match i {
        j if j == threads - 1 => data.len(), // last thread handle remaining work
        _ => chunk * (i + 1)
    };     

    let l_dat = data.to_owned(); // copy data for each thread
    let end_sig = tx.clone();

    thread::spawn(move || {
        let timer = Instant::now();

        let perm = XPermutationIterator::new(
            &l_dat, 
            |v| *v[0] >= start && *v[0] < end // skip branch that is outside the start/end
        );

        let mut counter = 0u64;

        for p in perm {
            // each permutation is stored in p
            counter += 1;
        }

        end_sig.send(i).unwrap();
    });
}

let main = thread::spawn(move || { // main thread
    let mut counter = 0;

    while counter < threads {
        let i = rx.recv().unwrap();
        // do something 
        counter += 1;
    }
});

main.join().unwrap();

Methods

impl<'a, F, T> XPermutationIterator<'a, F, T> where
    F: FnMut(&[&T]) -> bool,
    T: 'a, 
[src]

Important traits for XPermutationIterator<'a, F, T>
pub fn new(data: &'a [T], t: F) -> XPermutationIterator<F, T>[src]

Construct new XPermutationIterator object.

Parameters

  • data : &[T] - A data used for generate permutation.
  • t : FnMut(&[&T]) - A function that if return true, will make algorithm continue traversing the tree. Otherwise, the entire branch will be skip.

Trait Implementations

impl<'a, F, T> ExactSizeIterator for XPermutationIterator<'a, F, T> where
    F: FnMut(&[&T]) -> bool,
    T: 'a, 
[src]

impl<'a, F, T> Iterator for XPermutationIterator<'a, F, T> where
    F: FnMut(&[&T]) -> bool,
    T: 'a, 
[src]

type Item = Vec<&'a T>

The type of the elements being iterated over.

impl<'a, F, T> IteratorReset for XPermutationIterator<'a, F, T> where
    F: FnMut(&[&T]) -> bool,
    T: 'a, 
[src]

Auto Trait Implementations

impl<'a, F, T> RefUnwindSafe for XPermutationIterator<'a, F, T> where
    F: RefUnwindSafe,
    T: RefUnwindSafe

impl<'a, F, T> Send for XPermutationIterator<'a, F, T> where
    F: Send,
    T: Sync

impl<'a, F, T> Sync for XPermutationIterator<'a, F, T> where
    F: Sync,
    T: Sync

impl<'a, F, T> Unpin for XPermutationIterator<'a, F, T> where
    F: Unpin

impl<'a, F, T> UnwindSafe for XPermutationIterator<'a, F, T> where
    F: UnwindSafe,
    T: RefUnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<I> IntoIterator for I where
    I: Iterator
[src]

type Item = <I as Iterator>::Item

The type of the elements being iterated over.

type IntoIter = I

Which kind of iterator are we turning this into?

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.