use super::problem::*;
#[derive(Clone)]
pub struct Combine<T: Clone> {
elements: Vec<Vec<T>>,
index: Vec<usize>,
}
impl<T: Clone> Combine<T> {
pub fn new(elements: Vec<Vec<T>>) -> Self {
let index = elements.iter().map(|_| 0).collect();
Self { elements, index }
}
pub fn index(&self) -> &Vec<usize> {
&self.index
}
pub fn values(&self) -> Vec<T> {
self.elements
.iter()
.zip(self.index.iter())
.map(|(v, i)| v[*i].clone())
.collect()
}
pub fn step(&mut self) -> bool {
for i in 0..self.index.len() {
let n = self.index[i];
if n < self.elements[i].len() - 1 {
self.index[i] += 1;
return true;
}
if i != self.index.len() - 1 {
for j in 0..=i {
self.index[j] = 0;
}
}
}
false
}
pub fn next(&mut self) -> Option<Vec<T>> {
if self.step() {
Some(self.values())
} else {
None
}
}
}
pub fn combine_all(problem: &Problem, parameters: &Vec<Parameter>, expr: &Expr) -> Vec<Expr> {
let params_all = parameters.iter().map(|p| p.typ().all(problem)).collect();
let params_exp = parameters
.iter()
.map(|p| Expr::Parameter(p.clone()))
.collect::<Vec<_>>();
let mut combine = Combine::new(params_all);
let mut v = Vec::new();
loop {
let values = combine.values();
let all = params_exp.clone().into_iter().zip(values.clone()).collect();
let e = expr.substitute_all(all);
v.push(e);
if !combine.step() {
break;
}
}
v
}