use crate::heuristic::r#move::CutPoint;
pub struct CutCombinationIterator {
k: usize,
len: usize,
min_seg: usize,
entity_idx: usize,
positions: Vec<usize>,
done: bool,
}
impl CutCombinationIterator {
pub fn new(k: usize, len: usize, min_seg: usize, entity_idx: usize) -> Self {
let min_len = (k + 1) * min_seg;
if len < min_len {
return Self {
k,
len,
min_seg,
entity_idx,
positions: vec![],
done: true,
};
}
let mut positions = Vec::with_capacity(k);
for i in 0..k {
positions.push(min_seg * (i + 1));
}
Self {
k,
len,
min_seg,
entity_idx,
positions,
done: false,
}
}
fn advance(&mut self) -> bool {
if self.done || self.positions.is_empty() {
return false;
}
let k = self.k;
let len = self.len;
let min_seg = self.min_seg;
for i in (0..k).rev() {
let max_pos = len - min_seg * (k - i);
if self.positions[i] < max_pos {
self.positions[i] += 1;
for j in (i + 1)..k {
self.positions[j] = self.positions[j - 1] + min_seg;
}
return true;
}
}
self.done = true;
false
}
}
impl Iterator for CutCombinationIterator {
type Item = Vec<CutPoint>;
fn next(&mut self) -> Option<Self::Item> {
if self.done {
return None;
}
let cuts: Vec<CutPoint> = self
.positions
.iter()
.map(|&pos| CutPoint::new(self.entity_idx, pos))
.collect();
self.advance();
Some(cuts)
}
}
pub fn count_cut_combinations(k: usize, len: usize, min_seg: usize) -> usize {
let min_len = (k + 1) * min_seg;
if len < min_len {
return 0;
}
let free_slots = len - min_len + k;
binomial(free_slots, k)
}
pub fn binomial(n: usize, k: usize) -> usize {
if k > n {
return 0;
}
if k == 0 || k == n {
return 1;
}
let k = k.min(n - k); let mut result = 1;
for i in 0..k {
result = result * (n - i) / (i + 1);
}
result
}