pub trait Problem {
type Posibility: Copy;
type Solution;
fn extend_possibilities(
&self,
possibilities: &mut Vec<Self::Posibility>,
history: &[Self::Posibility],
);
fn undo(&mut self, last: &Self::Posibility, history: &[Self::Posibility]);
fn what_if(&mut self, decision: Self::Posibility);
fn is_solution(&self, history: &[Self::Posibility]) -> Option<Self::Solution>;
}
pub struct Solutions<P: Problem> {
decisions: Vec<P::Posibility>,
open: Vec<Candidate<P::Posibility>>,
history: Vec<P::Posibility>,
current: P,
}
impl<G: Problem> Solutions<G> {
pub fn new(init: G) -> Self {
let mut possible_moves = Vec::new();
init.extend_possibilities(&mut possible_moves, &[]);
let open = possible_moves
.iter()
.map(|pos| Candidate {
count: 1,
possibility: *pos,
})
.collect();
Self {
decisions: possible_moves,
open,
history: Vec::new(),
current: init,
}
}
}
impl<G: Problem> Iterator for Solutions<G> {
type Item = G::Solution;
fn next(&mut self) -> Option<Self::Item> {
while let Some(Candidate {
count,
possibility: mov,
}) = self.open.pop()
{
for _ in 0..self.history.len() as i32 - count + 1 {
let last = self.history.pop().unwrap();
self.current.undo(&last, &self.history);
}
self.current.what_if(mov);
self.history.push(mov);
if let Some(solution) = self.current.is_solution(&self.history) {
return Some(solution);
}
self.decisions.clear();
self.current
.extend_possibilities(&mut self.decisions, &self.history);
self.open
.extend(self.decisions.iter().map(|&position| Candidate {
count: count + 1,
possibility: position,
}))
}
None
}
}
struct Candidate<P> {
count: i32,
possibility: P,
}