pub struct Solver<T>{ /* private fields */ }Expand description
Implements the linked lists, which are structured in the following way
i0 ⟷ i1 ⟷ i2 ⟷ i3 ⟷ i4
⥯ ⥯ ⥯ ⥯ s0
o1 ⦿ ⦿ ⥯ ⥯ s1
o2 ⥯ ⥯ ⦿ ⥯ s2
o3 ⥯ ⦿ ⥯ ⦿ s3
o4 ⦿ ⥯ ⥯ ⥯ s4
⥯ ⥯ ⥯ ⥯where arrows denote links.
The spacers s0,…, also form a doubly circularly linked list.
i0 is the root node for the linked list of items i1,…,.i4
s0 is the root node for the spacers which link vertically to each other
⦿ denote the option elements which contain links up and down and also reference their “parent” item
We may set up and solve this problem with the following code
// Create Solver with 4 items
let mut s = Solver::new(4);
// Add options
s.add_option("o1", &[1, 2])
.add_option("o2", &[3])
.add_option("o3", &[2, 4])
.add_option("o4", &[1]);
// Iterate through all solutions
if let Some(solution) = s.next() {
assert_eq!(solution, ["o2","o3","o4"]);
Ok(())
}
else {
Err("No solution found".into())
}Implementations§
Source§impl<T: PartialEq + Debug + Clone> Solver<T>
impl<T: PartialEq + Debug + Clone> Solver<T>
Sourcepub fn new(n: usize) -> Self
pub fn new(n: usize) -> Self
Returns a solver with n items, all of which must be covered exactly
once
Sourcepub fn new_optional(mandatory: usize, opt: usize) -> Self
pub fn new_optional(mandatory: usize, opt: usize) -> Self
Returns a solver with n mandatory items and m optional items to be covered
This allows us to include items which may or may not be covered (but
still may not be covered more than once)
Example, where optional elements are after |
i1 i2 i3 i4 | i5
o1 1 0 1 0 | 0
o2 0 1 0 1 | 0
o3 1 0 0 0 | 1
o4 0 0 1 0 | 0
o5 0 0 1 0 | 1Here we can see taking [o1,o2] works, as does [o2,o3,o4], but not [o2,o3,o5], because then i4 would be double covered
The code that does this is
let mut s = Solver::new_optional(4,1);
s.add_option("o1", &[1, 3])
.add_option("o2", &[2, 4])
.add_option("o3", &[1, 5])
.add_option("o4", &[3])
.add_option("o5", &[3, 5]);
let s1 = s.next().unwrap_or_default();
let s2 = s.next().unwrap_or_default();
let s3 = s.next();
assert_eq!(s1,["o2","o1"]);
assert_eq!(s2,["o2","o3","o4"]);
assert_eq!(s3,None);Sourcepub fn add_option(&mut self, name: T, option: &[usize]) -> &mut Self
pub fn add_option(&mut self, name: T, option: &[usize]) -> &mut Self
Adds an option which would cover items defined by option, and with name `name
Specifically if our problems looks like
i0 ⟷ i1 ⟷ i2 ⟷ i3 ⟷ i4
⥯ ⥯ ⥯ ⥯ s0
o1 ⦿ ⦿ ⥯ ⥯ s1
o2 ⥯ ⥯ ⦿ ⥯ s2
o3 ⥯ ⦿ ⥯ ⦿ s3
o4 ⦿ ⥯ ⥯ ⥯ s4
⥯ ⥯ ⥯ ⥯then add_option("o5", &[1,2]) would take it to
i0 ⟷ i1 ⟷ i2 ⟷ i3 ⟷ i4
⥯ ⥯ ⥯ ⥯ s0
o1 ⦿ ⦿ ⥯ ⥯ s1
o2 ⥯ ⥯ ⦿ ⥯ s2
o3 ⥯ ⦿ ⥯ ⦿ s3
o4 ⦿ ⥯ ⥯ ⥯ s4
o5 ⦿ ⦿ ⥯ ⥯ s5
⥯ ⥯ ⥯ ⥯Sourcepub fn cover(&mut self, i: usize) -> Result<(), &'static str>
pub fn cover(&mut self, i: usize) -> Result<(), &'static str>
Covers item in column i
i.e. cover(2) would transform
i0 ⟷ i1 ⟷ i2 ⟷ i3 ⟷ i4
⥯ ⥯ ⥯ ⥯ s0
o1 ⦿ ⦿ ⥯ ⥯ s1
o2 ⥯ ⥯ ⦿ ⥯ s2
o3 ⥯ ⦿ ⥯ ⦿ s3
o4 ⦿ ⥯ ⥯ ⥯ s4
⥯ ⥯ ⥯ ⥯into
i0 ⟷ i1 ⟷ ⟷ ⟷ i3 ⟷ i4
⥯ ⥯ ⥯ s0
o1 ⦿ ⥯ ⥯ s1
o2 ⥯ ⦿ ⥯ s2
o3 ⥯ ⥯ ⦿ s3
o4 ⦿ ⥯ ⥯ s4
⥯ ⥯ ⥯Sourcepub fn output(&self) -> Vec<T>
pub fn output(&self) -> Vec<T>
Returns a solution in a human-understandable form
The solution vector sol_vec stores each of the OptionElements which
were used to cover the items in the solution. To turn this into
something understandable we find the spacer to its right, and use this
with a lookup table created earlier to map this to the names of options
Sourcepub fn select(&mut self, name: T) -> Result<(), &'static str>
pub fn select(&mut self, name: T) -> Result<(), &'static str>
Selects an option with the name name When setting up a general
constraint solution, this is how to search for specific answers e.g. a
Sudoku has all the constraints (items and options), and then the squares
filled out in the specific problem need to be selected
So for the problem
i1 i2 i3
o1 1 0 0
o2 1 0 0
o3 0 1 1Clearly both [o1,o3] and [o2,o3] are solutions, but if we select o1, then only one solution remains
let mut s = Solver::new(3);
s.add_option("o1", &[1])
.add_option("o2", &[1])
.add_option("o3", &[2, 3]);
// First get all solutions
let sols: Vec<Vec<&str>> = s.clone().collect();
assert_eq!(sols.len(), 2);
assert_eq!( vec!["o3", "o1"], sols[0]);
assert_eq!( vec!["o3", "o2"], sols[1]);
// Now select o1 and get all solutions
s.select("o1");
assert_eq!( vec!["o3"], s.next().unwrap());Trait Implementations§
Source§impl<T: Debug + PartialEq + Clone> Iterator for Solver<T>
impl<T: Debug + PartialEq + Clone> Iterator for Solver<T>
Source§fn next(&mut self) -> Option<Self::Item>
fn next(&mut self) -> Option<Self::Item>
Produces next solution by following algorithm X as described in tAoCP in Fasc 5c, Dancing Links, Knuth
Returns Some containing a vector of items if a solution remains, or
None when no more solutions remaining
Source§fn next_chunk<const N: usize>(
&mut self,
) -> Result<[Self::Item; N], IntoIter<Self::Item, N>>where
Self: Sized,
fn next_chunk<const N: usize>(
&mut self,
) -> Result<[Self::Item; N], IntoIter<Self::Item, N>>where
Self: Sized,
iter_next_chunk)N values. Read more1.0.0 · Source§fn size_hint(&self) -> (usize, Option<usize>)
fn size_hint(&self) -> (usize, Option<usize>)
1.0.0 · Source§fn count(self) -> usizewhere
Self: Sized,
fn count(self) -> usizewhere
Self: Sized,
1.0.0 · Source§fn last(self) -> Option<Self::Item>where
Self: Sized,
fn last(self) -> Option<Self::Item>where
Self: Sized,
Source§fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>>
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>>
iter_advance_by)n elements. Read more1.0.0 · Source§fn nth(&mut self, n: usize) -> Option<Self::Item>
fn nth(&mut self, n: usize) -> Option<Self::Item>
nth element of the iterator. Read more1.28.0 · Source§fn step_by(self, step: usize) -> StepBy<Self>where
Self: Sized,
fn step_by(self, step: usize) -> StepBy<Self>where
Self: Sized,
1.0.0 · Source§fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter>
fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter>
1.0.0 · Source§fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter>where
Self: Sized,
U: IntoIterator,
fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter>where
Self: Sized,
U: IntoIterator,
Source§fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
iter_intersperse)separator between adjacent
items of the original iterator. Read moreSource§fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>
fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>
iter_intersperse)separator
between adjacent items of the original iterator. Read more1.0.0 · Source§fn map<B, F>(self, f: F) -> Map<Self, F>
fn map<B, F>(self, f: F) -> Map<Self, F>
1.0.0 · Source§fn filter<P>(self, predicate: P) -> Filter<Self, P>
fn filter<P>(self, predicate: P) -> Filter<Self, P>
1.0.0 · Source§fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
1.0.0 · Source§fn enumerate(self) -> Enumerate<Self>where
Self: Sized,
fn enumerate(self) -> Enumerate<Self>where
Self: Sized,
1.0.0 · Source§fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
1.0.0 · Source§fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
1.57.0 · Source§fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
1.0.0 · Source§fn skip(self, n: usize) -> Skip<Self>where
Self: Sized,
fn skip(self, n: usize) -> Skip<Self>where
Self: Sized,
n elements. Read more1.0.0 · Source§fn take(self, n: usize) -> Take<Self>where
Self: Sized,
fn take(self, n: usize) -> Take<Self>where
Self: Sized,
n elements, or fewer
if the underlying iterator ends sooner. Read more1.0.0 · Source§fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
1.29.0 · Source§fn flatten(self) -> Flatten<Self>
fn flatten(self) -> Flatten<Self>
Source§fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N>
fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N>
iter_map_windows)f for each contiguous window of size N over
self and returns an iterator over the outputs of f. Like slice::windows(),
the windows during mapping overlap as well. Read more1.0.0 · Source§fn inspect<F>(self, f: F) -> Inspect<Self, F>
fn inspect<F>(self, f: F) -> Inspect<Self, F>
1.0.0 · Source§fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
Iterator. Read moreSource§fn try_collect<B>(
&mut self,
) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType
fn try_collect<B>( &mut self, ) -> <<Self::Item as Try>::Residual as Residual<B>>::TryType
iterator_try_collect)Source§fn collect_into<E>(self, collection: &mut E) -> &mut E
fn collect_into<E>(self, collection: &mut E) -> &mut E
iter_collect_into)1.0.0 · Source§fn partition<B, F>(self, f: F) -> (B, B)
fn partition<B, F>(self, f: F) -> (B, B)
Source§fn is_partitioned<P>(self, predicate: P) -> bool
fn is_partitioned<P>(self, predicate: P) -> bool
iter_is_partitioned)true precede all those that return false. Read more1.27.0 · Source§fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
1.27.0 · Source§fn try_for_each<F, R>(&mut self, f: F) -> R
fn try_for_each<F, R>(&mut self, f: F) -> R
1.0.0 · Source§fn fold<B, F>(self, init: B, f: F) -> B
fn fold<B, F>(self, init: B, f: F) -> B
1.51.0 · Source§fn reduce<F>(self, f: F) -> Option<Self::Item>
fn reduce<F>(self, f: F) -> Option<Self::Item>
Source§fn try_reduce<R>(
&mut self,
f: impl FnMut(Self::Item, Self::Item) -> R,
) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType
fn try_reduce<R>( &mut self, f: impl FnMut(Self::Item, Self::Item) -> R, ) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType
iterator_try_reduce)1.0.0 · Source§fn all<F>(&mut self, f: F) -> bool
fn all<F>(&mut self, f: F) -> bool
1.0.0 · Source§fn any<F>(&mut self, f: F) -> bool
fn any<F>(&mut self, f: F) -> bool
1.0.0 · Source§fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
1.30.0 · Source§fn find_map<B, F>(&mut self, f: F) -> Option<B>
fn find_map<B, F>(&mut self, f: F) -> Option<B>
Source§fn try_find<R>(
&mut self,
f: impl FnMut(&Self::Item) -> R,
) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType
fn try_find<R>( &mut self, f: impl FnMut(&Self::Item) -> R, ) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType
try_find)1.0.0 · Source§fn position<P>(&mut self, predicate: P) -> Option<usize>
fn position<P>(&mut self, predicate: P) -> Option<usize>
1.0.0 · Source§fn max(self) -> Option<Self::Item>
fn max(self) -> Option<Self::Item>
1.0.0 · Source§fn min(self) -> Option<Self::Item>
fn min(self) -> Option<Self::Item>
1.6.0 · Source§fn max_by_key<B, F>(self, f: F) -> Option<Self::Item>
fn max_by_key<B, F>(self, f: F) -> Option<Self::Item>
1.15.0 · Source§fn max_by<F>(self, compare: F) -> Option<Self::Item>
fn max_by<F>(self, compare: F) -> Option<Self::Item>
1.6.0 · Source§fn min_by_key<B, F>(self, f: F) -> Option<Self::Item>
fn min_by_key<B, F>(self, f: F) -> Option<Self::Item>
1.15.0 · Source§fn min_by<F>(self, compare: F) -> Option<Self::Item>
fn min_by<F>(self, compare: F) -> Option<Self::Item>
1.0.0 · Source§fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
1.36.0 · Source§fn copied<'a, T>(self) -> Copied<Self>
fn copied<'a, T>(self) -> Copied<Self>
Source§fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N>where
Self: Sized,
fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N>where
Self: Sized,
iter_array_chunks)N elements of the iterator at a time. Read more1.11.0 · Source§fn product<P>(self) -> P
fn product<P>(self) -> P
Source§fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering
fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering
iter_order_by)Iterator with those
of another with respect to the specified comparison function. Read more1.5.0 · Source§fn partial_cmp<I>(self, other: I) -> Option<Ordering>
fn partial_cmp<I>(self, other: I) -> Option<Ordering>
PartialOrd elements of
this Iterator with those of another. The comparison works like short-circuit
evaluation, returning a result without comparing the remaining elements.
As soon as an order can be determined, the evaluation stops and a result is returned. Read moreSource§fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering>where
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>,
fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering>where
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>,
iter_order_by)Iterator with those
of another with respect to the specified comparison function. Read moreSource§fn eq_by<I, F>(self, other: I, eq: F) -> bool
fn eq_by<I, F>(self, other: I, eq: F) -> bool
iter_order_by)1.5.0 · Source§fn lt<I>(self, other: I) -> bool
fn lt<I>(self, other: I) -> bool
Iterator are lexicographically
less than those of another. Read more1.5.0 · Source§fn le<I>(self, other: I) -> bool
fn le<I>(self, other: I) -> bool
Iterator are lexicographically
less or equal to those of another. Read more1.5.0 · Source§fn gt<I>(self, other: I) -> bool
fn gt<I>(self, other: I) -> bool
Iterator are lexicographically
greater than those of another. Read more1.5.0 · Source§fn ge<I>(self, other: I) -> bool
fn ge<I>(self, other: I) -> bool
Iterator are lexicographically
greater than or equal to those of another. Read more