pub(crate) struct WalkExpansion {
slot_bundle: Vec<u32>,
slots: Vec<Vec<u32>>,
cursor: Vec<usize>,
chosen: Vec<u32>,
started: bool,
finished: bool,
}
impl WalkExpansion {
pub(crate) fn new(slot_bundle: Vec<u32>, slots: Vec<Vec<u32>>) -> Self {
let n = slots.len();
Self {
slot_bundle,
slots,
cursor: vec![0; n],
chosen: vec![0; n],
started: false,
finished: false,
}
}
pub(crate) fn next_assignment_into(&mut self, out: &mut Vec<u32>) -> bool {
let n = self.slots.len();
if n == 0 {
if self.started {
return false;
}
self.started = true;
out.clear();
return true;
}
loop {
if self.finished {
return false;
}
if self.started {
let mut j = n;
loop {
if j == 0 {
self.finished = true;
return false;
}
j -= 1;
self.cursor[j] += 1;
if self.cursor[j] < self.slots[j].len() {
self.chosen[j] = self.slots[j][self.cursor[j]];
for k in j + 1..n {
self.cursor[k] = 0;
self.chosen[k] = self.slots[k][0];
}
break;
}
}
} else {
self.started = true;
for i in 0..n {
self.cursor[i] = 0;
self.chosen[i] = self.slots[i][0];
}
}
if self.same_bundle_distinct() {
out.clear();
out.extend_from_slice(&self.chosen);
return true;
}
}
}
fn same_bundle_distinct(&self) -> bool {
for i in 0..self.slots.len() {
for j in i + 1..self.slots.len() {
if self.slot_bundle[i] == self.slot_bundle[j] && self.chosen[i] == self.chosen[j] {
return false;
}
}
}
true
}
}