use std::collections::BTreeSet;
pub struct KPermutations {
n: usize,
k: usize,
a: Vec<usize>,
edge: usize,
first: bool,
}
impl KPermutations {
pub fn new(n: usize, k: usize) -> Self {
let a: Vec<_> = (0..n).collect();
KPermutations {
n,
k,
a,
edge: k - 1,
first: true,
}
}
}
impl Iterator for KPermutations {
type Item = Vec<usize>;
fn next(&mut self) -> Option<Self::Item> {
if self.k == 1 {
return self.a.pop().map(|ix| vec![ix]);
}
if self.first {
self.first = false;
return Some(self.a[0..self.k].to_vec());
}
let mut j = self.k;
while j < self.n && self.a[self.edge] >= self.a[j] {
j += 1;
}
if j < self.n {
self.a.swap(self.edge, j);
} else {
if self.k < (self.n + 2) {
let num_items = (self.n - self.k) / 2;
for ix in 0..num_items {
self.a.swap(self.k + ix, self.n - ix - 1)
}
}
let mut i = self.edge - 1;
while self.a[i] >= self.a[i + 1] {
if i == 0 {
return None;
}
i -= 1;
}
j = self.n - 1;
while j > i && self.a[i] >= self.a[j] {
j -= 1;
}
self.a.swap(i, j);
if (i + 1) < (self.n + 2) {
let num_items = (self.n - i - 1) / 2;
for ix in 0..num_items {
self.a.swap(i + 1 + ix, self.n - ix - 1)
}
}
}
Some(self.a[0..self.k].to_vec())
}
}
pub struct KPermutationsFilter {
classes: Vec<usize>,
yielded: BTreeSet<Vec<usize>>,
perms: KPermutations,
}
impl KPermutationsFilter {
pub fn new(classes: Vec<usize>, k: usize) -> Self {
let n = classes.len();
KPermutationsFilter {
classes,
yielded: BTreeSet::new(),
perms: KPermutations::new(n, k),
}
}
fn unique_class_permutation(&mut self, item: &[usize]) -> bool {
let class_perm: Vec<_> =
item.iter().map(|ix| self.classes[*ix]).collect();
self.yielded.insert(class_perm)
}
}
impl Iterator for KPermutationsFilter {
type Item = Vec<usize>;
fn next(&mut self) -> Option<Self::Item> {
loop {
let item = self.perms.next();
match item {
None => return None,
Some(ref ixs) => {
if self.unique_class_permutation(ixs) {
return item;
}
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::{KPermutations, KPermutationsFilter};
use log::info;
fn init() {
let _ = env_logger::Builder::from_env(
env_logger::Env::default().default_filter_or("info"),
)
.is_test(true)
.try_init();
}
#[test]
fn test_kpermutations_1_1() {
init();
let perm = KPermutations::new(1, 1);
let perms: Vec<_> = perm.collect();
let expected_count = 1;
assert_eq!(expected_count, perms.len());
for p in &perms {
info!("Received {:?}", p);
}
}
#[test]
fn test_kpermutations_5_1() {
init();
let perm = KPermutations::new(5, 1);
let perms: Vec<_> = perm.collect();
let expected_count = 5;
assert_eq!(expected_count, perms.len());
for p in &perms {
info!("Received {:?}", p);
}
}
#[test]
fn test_kpermutations_5_2() {
init();
let perm = KPermutations::new(5, 2);
let perms: Vec<_> = perm.collect();
let expected_count = 20;
assert_eq!(expected_count, perms.len());
for p in &perms {
info!("Received {:?}", p);
}
}
#[test]
fn test_kpermutations_2_2() {
init();
let perm = KPermutations::new(2, 2);
let perms: Vec<_> = perm.collect();
let expected_count = 2;
assert_eq!(expected_count, perms.len());
for p in &perms {
info!("Received {:?}", p);
}
}
#[test]
fn test_kpermutationsfilter_5_2_2() {
init();
let classes = vec![0, 0, 1, 1, 1];
let perm = KPermutationsFilter::new(classes, 2);
let perms: Vec<_> = perm.collect();
let expected_count = 4;
assert_eq!(expected_count, perms.len());
for p in &perms {
info!("Received {:?}", p);
}
}
#[test]
fn test_kpermutationsfilter_2_1_2() {
init();
let classes = vec![0, 0];
let perm = KPermutationsFilter::new(classes, 2);
let perms: Vec<_> = perm.collect();
let expected_count = 1;
assert_eq!(expected_count, perms.len());
for p in &perms {
info!("Received {:?}", p);
}
}
#[test]
fn test_kpermutationsfilter_2_2_2() {
init();
let classes = vec![0, 1];
let perm = KPermutationsFilter::new(classes, 2);
let perms: Vec<_> = perm.collect();
let expected_count = 2;
assert_eq!(expected_count, perms.len());
for p in &perms {
info!("Received {:?}", p);
}
}
}