use std::collections::VecDeque;
enum Funcs {
F1(usize, usize, usize),
F2(usize, usize, usize),
F3(usize, usize, usize),
B1(usize, usize, usize),
B11(usize, usize, usize),
B2(usize, usize, usize)
}
pub struct IncSeqIterator {
a:Vec<u32>,
stack:Vec<Funcs>,
buffer:VecDeque<Vec<u32>>
}
impl IncSeqIterator {
pub fn new(n:u32, k:u32) -> Self {
let mut a = vec![0; (n+1) as usize];
for j in 1..=k {
a[(n-k+j) as usize] = j-1;
}
let mut buffer = VecDeque::new();
if k == 0 {
if n == 0 {
buffer.push_back(Vec::new());
}
return IncSeqIterator{a, stack: Vec::new(), buffer};
}
if k == 1 {
let mut res = IncSeqIterator{a, stack: Vec::new(), buffer};
res.visit(); return res;
}
let stack = vec![Funcs::F1(k as usize, n as usize, 0)];
IncSeqIterator{a, stack, buffer}
}
fn run(&mut self) -> bool {
match self.stack.pop() {
Some(Funcs::F1(mu, nu, sigma)) => {
self.f1(mu, nu, sigma);
true
}
Some(Funcs::F2(mu, nu, sigma)) => {
self.f2(mu, nu, sigma);
true
}
Some(Funcs::F3(mu, nu, sigma)) => {
self.f3(mu, nu, sigma);
true
}
Some(Funcs::B1(mu, nu, sigma)) => {
self.b1(mu, nu, sigma);
true
}
Some(Funcs::B11(mu, nu, sigma)) => {
self.b11(mu, nu, sigma);
true
}
Some(Funcs::B2(mu, nu, sigma)) => {
self.b2(mu, nu, sigma);
true
}
None => false,
}
}
fn visit(&mut self) {
let res: Vec<u32> = self.a.iter().skip(1).cloned().collect();
self.buffer.push_back(res);
}
fn f1(&mut self, mu:usize, nu:usize, sigma:usize) {
self.stack.push(Funcs::F2(mu, nu, sigma)); if mu == 2 {
self.visit()
} else {
self.stack.push(Funcs::F1(mu-1, nu-1, (mu+sigma)%2));
}
}
fn f2(&mut self, mu:usize, nu:usize, sigma:usize) {
if nu == mu + 1 {
self.a[mu] = (mu - 1) as u32;
self.visit();
while self.a[nu] > 0 {
self.a[nu] = self.a[nu] - 1;
self.visit();
}
} else if nu > mu + 1 {
if (mu + sigma) % 2 == 1 {
self.a[nu - 1] = (mu - 1) as u32;
} else {
self.a[mu] = (mu - 1) as u32;
}
self.stack.push(Funcs::F3(mu, nu, sigma));
if (self.a[nu] + sigma as u32) % 2 == 1 {
self.stack.push(Funcs::B1(mu, nu-1, 0));
} else {
self.stack.push(Funcs::F1(mu, nu-1, 0));
}
}
}
fn f3(&mut self, mu:usize, nu:usize, sigma:usize) {
if self.a[nu] > 0 {
self.stack.push(Funcs::F3(mu, nu, sigma));
self.a[nu] = self.a[nu] - 1;
if (self.a[nu] + sigma as u32) % 2 == 1 {
self.stack.push(Funcs::B1(mu, nu - 1, 0));
} else {
self.stack.push(Funcs::F1(mu, nu - 1, 0));
}
}
}
fn b1(&mut self, mu:usize, nu:usize, sigma:usize) {
self.stack.push(Funcs::B2(mu, nu, sigma));
if nu == mu + 1 {
while self.a[nu] < (mu - 1) as u32 {
self.visit();
self.a[nu] += 1;
}
self.visit();
self.a[mu] = 0;
} else if nu > mu + 1 {
self.stack.push(Funcs::B11(mu, nu, sigma));
if (self.a[nu] + sigma as u32) % 2 == 1 {
self.stack.push(Funcs::F1(mu, nu-1, 0));
} else {
self.stack.push(Funcs::B1(mu, nu-1, 0));
}
}
}
fn b11(&mut self, mu:usize, nu:usize, sigma:usize) {
if self.a[nu] < (mu - 1) as u32 {
self.stack.push(Funcs::B11(mu, nu, sigma));
self.a[nu] += 1;
if (self.a[nu] + sigma as u32) % 2 == 1 {
self.stack.push(Funcs::F1(mu, nu-1, 0));
} else {
self.stack.push(Funcs::B1(mu, nu-1, 0));
}
} else {
if (mu + sigma) % 2 == 1 {
self.a[nu - 1] = 0;
} else {
self.a[mu] = 0;
}
}
}
fn b2(&mut self, mu:usize, nu:usize, sigma:usize) {
if mu == 2 {
self.visit();
} else {
self.stack.push(Funcs::B1(mu-1, nu-1, (mu+sigma)%2 ));
}
}
}
impl Iterator for IncSeqIterator {
type Item = Vec<u32>;
fn next(&mut self) -> Option<Self::Item> {
while self.buffer.len() == 0 && self.run() {
()
}
return self.buffer.pop_front();
}
}