1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//! Types defining solutions and help working with them

use std::iter::FilterMap;

/// Items of some intermediate solution.
///
/// This type is used as item in iterative solvers.
/// Each enum is a test of the next best candidate solution.
/// The iterator is exhausted when no more candidates can be tried.
#[derive(Debug)]
pub enum CandidateSolution<T = usize> {
    /// Satisfactory solution (but too short)
    Incomplete,
    /// Satisfying and complete solution including its values
    Sat(Vec<T>),
    /// Unsatisfying (and maybe too short) solution including its values
    Unsat(Vec<T>),
}

/// Items of completed solutions.
#[derive(Debug)]
pub enum Solution<T = usize> {
    /// Satisfying and complete solution including its values
    Sat(Vec<T>),
    /// Unsatisfying (and maybe too short) solution including its values
    Unsat(Vec<T>),
}

type OptionalSat = Option<Vec<usize>>;

/// Filter interesting solution candidates
///
pub trait IterSolveExt: Iterator<Item = CandidateSolution> + Sized {
    /// Only yield satisfying and unsatisfying solutions
    fn solution_iter(self) -> FilterMap<Self, fn(CandidateSolution) -> Option<Solution>> {
        self.filter_map(|s| match s {
            CandidateSolution::Sat(sat) => Some(Solution::Sat(sat)),
            CandidateSolution::Unsat(unsat) => Some(Solution::Unsat(unsat)),
            CandidateSolution::Incomplete => None,
        })
    }
    // Only yield satisfying solutions
    fn sat_iter(self) -> FilterMap<Self, fn(CandidateSolution) -> OptionalSat> {
        self.filter_map(|s| match s {
            CandidateSolution::Sat(sat) => Some(sat),
            _ => None,
        })
    }
}

impl<T: Iterator<Item = CandidateSolution>> IterSolveExt for T {}