Edition 2021
This commit is contained in:
parent
ee6bf20aba
commit
74ea9c497f
@ -10,6 +10,7 @@ license = "MIT"
|
|||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["constraint", "finite", "domain", "puzzle", "sudoku"]
|
keywords = ["constraint", "finite", "domain", "puzzle", "sudoku"]
|
||||||
categories = ["science"]
|
categories = ["science"]
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bit-set = "0.4"
|
bit-set = "0.4"
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use ::{Constraint,PsResult,PuzzleSearch,Val,VarToken};
|
use crate::{Constraint,PsResult,PuzzleSearch,Val,VarToken};
|
||||||
|
|
||||||
pub struct AllDifferent {
|
pub struct AllDifferent {
|
||||||
vars: Vec<VarToken>,
|
vars: Vec<VarToken>,
|
||||||
@ -30,14 +30,14 @@ impl AllDifferent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Constraint for AllDifferent {
|
impl Constraint for AllDifferent {
|
||||||
fn vars<'a>(&'a self) -> Box<Iterator<Item=&'a VarToken> + 'a> {
|
fn vars<'a>(&'a self) -> Box<dyn Iterator<Item=&'a VarToken> + 'a> {
|
||||||
Box::new(self.vars.iter())
|
Box::new(self.vars.iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_assigned(&self, search: &mut PuzzleSearch, var: VarToken, val: Val)
|
fn on_assigned(&self, search: &mut PuzzleSearch, var: VarToken, val: Val)
|
||||||
-> PsResult<()> {
|
-> PsResult<()> {
|
||||||
for &var2 in self.vars.iter().filter(|&v| *v != var) {
|
for &var2 in self.vars.iter().filter(|&v| *v != var) {
|
||||||
try!(search.remove_candidate(var2, val));
|
r#try!(search.remove_candidate(var2, val));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -67,7 +67,7 @@ impl Constraint for AllDifferent {
|
|||||||
// As many as variables as candidates.
|
// As many as variables as candidates.
|
||||||
for (&val, &opt) in all_candidates.iter() {
|
for (&val, &opt) in all_candidates.iter() {
|
||||||
if let Some(var) = opt {
|
if let Some(var) = opt {
|
||||||
try!(search.set_candidate(var, val));
|
r#try!(search.set_candidate(var, val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ impl Constraint for AllDifferent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn substitute(&self, from: VarToken, to: VarToken)
|
fn substitute(&self, from: VarToken, to: VarToken)
|
||||||
-> PsResult<Rc<Constraint>> {
|
-> PsResult<Rc<dyn Constraint>> {
|
||||||
if let Some(idx) = self.vars.iter().position(|&var| var == from) {
|
if let Some(idx) = self.vars.iter().position(|&var| var == from) {
|
||||||
if !self.vars.contains(&to) {
|
if !self.vars.contains(&to) {
|
||||||
let mut new_vars = self.vars.clone();
|
let mut new_vars = self.vars.clone();
|
||||||
@ -91,7 +91,7 @@ impl Constraint for AllDifferent {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use ::{Puzzle,Val};
|
use crate::{Puzzle,Val};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_contradiction() {
|
fn test_contradiction() {
|
||||||
|
@ -4,7 +4,7 @@ use std::rc::Rc;
|
|||||||
use num_rational::Ratio;
|
use num_rational::Ratio;
|
||||||
use num_traits::Zero;
|
use num_traits::Zero;
|
||||||
|
|
||||||
use ::{Constraint,LinExpr,PsResult,PuzzleSearch,Val,VarToken};
|
use crate::{Constraint,LinExpr,PsResult,PuzzleSearch,Val,VarToken};
|
||||||
|
|
||||||
pub struct Equality {
|
pub struct Equality {
|
||||||
// The equation: 0 = constant + coef1 * var1 + coef2 * var2 + ...
|
// The equation: 0 = constant + coef1 * var1 + coef2 * var2 + ...
|
||||||
@ -32,7 +32,7 @@ impl Equality {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Constraint for Equality {
|
impl Constraint for Equality {
|
||||||
fn vars<'a>(&'a self) -> Box<Iterator<Item=&'a VarToken> + 'a> {
|
fn vars<'a>(&'a self) -> Box<dyn Iterator<Item=&'a VarToken> + 'a> {
|
||||||
Box::new(self.eqn.coef.keys())
|
Box::new(self.eqn.coef.keys())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ impl Constraint for Equality {
|
|||||||
// sum + coef * var = 0.
|
// sum + coef * var = 0.
|
||||||
let val = -sum / coef;
|
let val = -sum / coef;
|
||||||
if val.is_integer() {
|
if val.is_integer() {
|
||||||
try!(search.set_candidate(var, val.to_integer()));
|
r#try!(search.set_candidate(var, val.to_integer()));
|
||||||
} else {
|
} else {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
@ -78,7 +78,7 @@ impl Constraint for Equality {
|
|||||||
let mut sum_max = self.eqn.constant;
|
let mut sum_max = self.eqn.constant;
|
||||||
|
|
||||||
for (&var, &coef) in self.eqn.coef.iter() {
|
for (&var, &coef) in self.eqn.coef.iter() {
|
||||||
let (min_val, max_val) = try!(search.get_min_max(var));
|
let (min_val, max_val) = r#try!(search.get_min_max(var));
|
||||||
if coef > Ratio::zero() {
|
if coef > Ratio::zero() {
|
||||||
sum_min = sum_min + coef * Ratio::from_integer(min_val);
|
sum_min = sum_min + coef * Ratio::from_integer(min_val);
|
||||||
sum_max = sum_max + coef * Ratio::from_integer(max_val);
|
sum_max = sum_max + coef * Ratio::from_integer(max_val);
|
||||||
@ -104,7 +104,7 @@ impl Constraint for Equality {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (min_val, max_val) = try!(search.get_min_max(var));
|
let (min_val, max_val) = r#try!(search.get_min_max(var));
|
||||||
let (min_bnd, max_bnd);
|
let (min_bnd, max_bnd);
|
||||||
|
|
||||||
if coef > Ratio::zero() {
|
if coef > Ratio::zero() {
|
||||||
@ -117,7 +117,7 @@ impl Constraint for Equality {
|
|||||||
|
|
||||||
if min_val < min_bnd || max_bnd < max_val {
|
if min_val < min_bnd || max_bnd < max_val {
|
||||||
let (new_min, new_max)
|
let (new_min, new_max)
|
||||||
= try!(search.bound_candidate_range(var, min_bnd, max_bnd));
|
= r#try!(search.bound_candidate_range(var, min_bnd, max_bnd));
|
||||||
|
|
||||||
if coef > Ratio::zero() {
|
if coef > Ratio::zero() {
|
||||||
sum_min = sum_min + coef * Ratio::from_integer(new_min - min_val);
|
sum_min = sum_min + coef * Ratio::from_integer(new_min - min_val);
|
||||||
@ -135,7 +135,7 @@ impl Constraint for Equality {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn substitute(&self, from: VarToken, to: VarToken)
|
fn substitute(&self, from: VarToken, to: VarToken)
|
||||||
-> PsResult<Rc<Constraint>> {
|
-> PsResult<Rc<dyn Constraint>> {
|
||||||
let mut eqn = self.eqn.clone();
|
let mut eqn = self.eqn.clone();
|
||||||
if let Some(coef) = eqn.coef.remove(&from) {
|
if let Some(coef) = eqn.coef.remove(&from) {
|
||||||
eqn = eqn + coef * to;
|
eqn = eqn + coef * to;
|
||||||
@ -147,7 +147,7 @@ impl Constraint for Equality {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use ::{Puzzle,Val};
|
use crate::{Puzzle,Val};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_contradiction() {
|
fn test_contradiction() {
|
||||||
|
@ -7,12 +7,12 @@
|
|||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use ::{PsResult,PuzzleSearch,Val,VarToken};
|
use crate::{PsResult,PuzzleSearch,Val,VarToken};
|
||||||
|
|
||||||
/// Constraint trait.
|
/// Constraint trait.
|
||||||
pub trait Constraint {
|
pub trait Constraint {
|
||||||
/// An iterator over the variables that are involved in the constraint.
|
/// An iterator over the variables that are involved in the constraint.
|
||||||
fn vars<'a>(&'a self) -> Box<Iterator<Item=&'a VarToken> + 'a>;
|
fn vars<'a>(&'a self) -> Box<dyn Iterator<Item=&'a VarToken> + 'a>;
|
||||||
|
|
||||||
/// Applied after a variable has been assigned.
|
/// Applied after a variable has been assigned.
|
||||||
fn on_assigned(&self, _search: &mut PuzzleSearch, _var: VarToken, _val: Val)
|
fn on_assigned(&self, _search: &mut PuzzleSearch, _var: VarToken, _val: Val)
|
||||||
@ -30,7 +30,7 @@ pub trait Constraint {
|
|||||||
/// Returns a new constraint with all instances of "from" replaced
|
/// Returns a new constraint with all instances of "from" replaced
|
||||||
/// with "to", or Err if a contradiction was found.
|
/// with "to", or Err if a contradiction was found.
|
||||||
fn substitute(&self, from: VarToken, to: VarToken)
|
fn substitute(&self, from: VarToken, to: VarToken)
|
||||||
-> PsResult<Rc<Constraint>>;
|
-> PsResult<Rc<dyn Constraint>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use self::alldifferent::AllDifferent;
|
pub use self::alldifferent::AllDifferent;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use std::iter;
|
use std::iter;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use ::{Constraint,PsResult,PuzzleSearch,VarToken};
|
use crate::{Constraint,PsResult,PuzzleSearch,VarToken};
|
||||||
|
|
||||||
pub struct Unify {
|
pub struct Unify {
|
||||||
var1: VarToken,
|
var1: VarToken,
|
||||||
@ -33,7 +33,7 @@ impl Unify {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Constraint for Unify {
|
impl Constraint for Unify {
|
||||||
fn vars<'a>(&'a self) -> Box<Iterator<Item=&'a VarToken> + 'a> {
|
fn vars<'a>(&'a self) -> Box<dyn Iterator<Item=&'a VarToken> + 'a> {
|
||||||
if self.var1 != self.var2 {
|
if self.var1 != self.var2 {
|
||||||
Box::new(iter::once(&self.var1).chain(iter::once(&self.var2)))
|
Box::new(iter::once(&self.var1).chain(iter::once(&self.var2)))
|
||||||
} else {
|
} else {
|
||||||
@ -50,7 +50,7 @@ impl Constraint for Unify {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn substitute(&self, from: VarToken, to: VarToken)
|
fn substitute(&self, from: VarToken, to: VarToken)
|
||||||
-> PsResult<Rc<Constraint>> {
|
-> PsResult<Rc<dyn Constraint>> {
|
||||||
let var1 = if self.var1 == from { to } else { self.var1 };
|
let var1 = if self.var1 == from { to } else { self.var1 };
|
||||||
let var2 = if self.var2 == from { to } else { self.var2 };
|
let var2 = if self.var2 == from { to } else { self.var2 };
|
||||||
Ok(Rc::new(Unify{ var1: var1, var2: var2 }))
|
Ok(Rc::new(Unify{ var1: var1, var2: var2 }))
|
||||||
@ -59,7 +59,7 @@ impl Constraint for Unify {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use ::Puzzle;
|
use crate::Puzzle;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unify_alldifferent() {
|
fn test_unify_alldifferent() {
|
||||||
|
@ -9,9 +9,9 @@ use std::collections::HashMap;
|
|||||||
use std::ops;
|
use std::ops;
|
||||||
use num_rational::Rational32;
|
use num_rational::Rational32;
|
||||||
|
|
||||||
pub use constraint::Constraint;
|
pub use crate::constraint::Constraint;
|
||||||
pub use puzzle::Puzzle;
|
pub use crate::puzzle::Puzzle;
|
||||||
pub use puzzle::PuzzleSearch;
|
pub use crate::puzzle::PuzzleSearch;
|
||||||
|
|
||||||
/// A puzzle variable token.
|
/// A puzzle variable token.
|
||||||
#[derive(Copy,Clone,Debug,Eq,Hash,PartialEq)]
|
#[derive(Copy,Clone,Debug,Eq,Hash,PartialEq)]
|
||||||
|
@ -7,7 +7,7 @@ use std::ops::{Add,Mul,Neg,Sub};
|
|||||||
use num_rational::{Ratio,Rational32};
|
use num_rational::{Ratio,Rational32};
|
||||||
use num_traits::{One,Zero};
|
use num_traits::{One,Zero};
|
||||||
|
|
||||||
use ::{Coef,LinExpr,VarToken};
|
use crate::{Coef,LinExpr,VarToken};
|
||||||
|
|
||||||
macro_rules! impl_commutative_op {
|
macro_rules! impl_commutative_op {
|
||||||
($LHS:ident + $RHS:ident) => {
|
($LHS:ident + $RHS:ident) => {
|
||||||
@ -219,7 +219,7 @@ impl_subtract_op!(LinExpr - LinExpr);
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use num_rational::Ratio;
|
use num_rational::Ratio;
|
||||||
use ::Puzzle;
|
use crate::Puzzle;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ops() {
|
fn test_ops() {
|
||||||
|
@ -9,8 +9,8 @@ use std::ops;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use bit_set::BitSet;
|
use bit_set::BitSet;
|
||||||
|
|
||||||
use ::{Constraint,LinExpr,PsResult,Solution,Val,VarToken};
|
use crate::{Constraint,LinExpr,PsResult,Solution,Val,VarToken};
|
||||||
use constraint;
|
use crate::constraint;
|
||||||
|
|
||||||
/// A collection of candidates.
|
/// A collection of candidates.
|
||||||
#[derive(Clone,Debug,Eq,PartialEq)]
|
#[derive(Clone,Debug,Eq,PartialEq)]
|
||||||
@ -40,14 +40,14 @@ pub struct Puzzle {
|
|||||||
candidates: Vec<Candidates>,
|
candidates: Vec<Candidates>,
|
||||||
|
|
||||||
// The list of puzzle constraints.
|
// The list of puzzle constraints.
|
||||||
constraints: Vec<Rc<Constraint>>,
|
constraints: Vec<Rc<dyn Constraint>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The puzzle constraints, and the variables that wake them up.
|
/// The puzzle constraints, and the variables that wake them up.
|
||||||
struct PuzzleConstraints {
|
struct PuzzleConstraints {
|
||||||
// The list of puzzle constraints, possibly with variables
|
// The list of puzzle constraints, possibly with variables
|
||||||
// substituted out.
|
// substituted out.
|
||||||
constraints: Vec<Rc<Constraint>>,
|
constraints: Vec<Rc<dyn Constraint>>,
|
||||||
|
|
||||||
// The list of constraints that each variable affects. These will
|
// The list of constraints that each variable affects. These will
|
||||||
// be woken up when the variable's candidates are changed.
|
// be woken up when the variable's candidates are changed.
|
||||||
@ -78,7 +78,7 @@ impl Candidates {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get an iterator over all of the candidates of a variable.
|
/// Get an iterator over all of the candidates of a variable.
|
||||||
fn iter<'a>(&'a self) -> Box<Iterator<Item=Val> + 'a> {
|
fn iter<'a>(&'a self) -> Box<dyn Iterator<Item=Val> + 'a> {
|
||||||
match self {
|
match self {
|
||||||
&Candidates::None => Box::new(iter::empty()),
|
&Candidates::None => Box::new(iter::empty()),
|
||||||
&Candidates::Value(val) => Box::new(iter::once(val)),
|
&Candidates::Value(val) => Box::new(iter::once(val)),
|
||||||
@ -467,7 +467,7 @@ impl PuzzleConstraints {
|
|||||||
let mut new_constraints = self.constraints.clone();
|
let mut new_constraints = self.constraints.clone();
|
||||||
|
|
||||||
for cidx in self.wake[idx].iter() {
|
for cidx in self.wake[idx].iter() {
|
||||||
let rc = try!(self.constraints[cidx].substitute(from, to));
|
let rc = r#try!(self.constraints[cidx].substitute(from, to));
|
||||||
new_constraints[cidx] = rc;
|
new_constraints[cidx] = rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,7 +479,7 @@ impl PuzzleConstraints {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Determine which variables wake up which constraints.
|
/// Determine which variables wake up which constraints.
|
||||||
fn init_wake(constraints: &Vec<Rc<Constraint>>, num_vars: usize)
|
fn init_wake(constraints: &Vec<Rc<dyn Constraint>>, num_vars: usize)
|
||||||
-> Vec<BitSet> {
|
-> Vec<BitSet> {
|
||||||
let mut wake = vec![BitSet::new(); num_vars];
|
let mut wake = vec![BitSet::new(); num_vars];
|
||||||
for cidx in 0..constraints.len() {
|
for cidx in 0..constraints.len() {
|
||||||
@ -539,7 +539,7 @@ impl<'a> PuzzleSearch<'a> {
|
|||||||
|
|
||||||
/// Get an iterator over the candidates to an unassigned variable.
|
/// Get an iterator over the candidates to an unassigned variable.
|
||||||
pub fn get_unassigned(&'a self, var: VarToken)
|
pub fn get_unassigned(&'a self, var: VarToken)
|
||||||
-> Box<Iterator<Item=Val> + 'a> {
|
-> Box<dyn Iterator<Item=Val> + 'a> {
|
||||||
let VarToken(idx) = var;
|
let VarToken(idx) = var;
|
||||||
match &self.vars[idx] {
|
match &self.vars[idx] {
|
||||||
&VarState::Assigned(_) => Box::new(iter::empty()),
|
&VarState::Assigned(_) => Box::new(iter::empty()),
|
||||||
@ -731,7 +731,7 @@ impl<'a> PuzzleSearch<'a> {
|
|||||||
for cidx in 0..self.constraints.constraints.len() {
|
for cidx in 0..self.constraints.constraints.len() {
|
||||||
if self.constraints.wake[idx].contains(cidx) {
|
if self.constraints.wake[idx].contains(cidx) {
|
||||||
let constraint = self.constraints.constraints[cidx].clone();
|
let constraint = self.constraints.constraints[cidx].clone();
|
||||||
try!(constraint.on_assigned(self, var, val));
|
r#try!(constraint.on_assigned(self, var, val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -761,7 +761,7 @@ impl<'a> PuzzleSearch<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(val) = gimme {
|
if let Some(val) = gimme {
|
||||||
try!(self.assign(idx, val));
|
r#try!(self.assign(idx, val));
|
||||||
last_gimme = idx;
|
last_gimme = idx;
|
||||||
} else if idx == last_gimme {
|
} else if idx == last_gimme {
|
||||||
break;
|
break;
|
||||||
@ -775,7 +775,7 @@ impl<'a> PuzzleSearch<'a> {
|
|||||||
let wake = mem::replace(&mut self.wake, BitSet::new());
|
let wake = mem::replace(&mut self.wake, BitSet::new());
|
||||||
for cidx in wake.iter() {
|
for cidx in wake.iter() {
|
||||||
let constraint = self.constraints.constraints[cidx].clone();
|
let constraint = self.constraints.constraints[cidx].clone();
|
||||||
try!(constraint.on_updated(self));
|
r#try!(constraint.on_updated(self));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -816,14 +816,14 @@ impl<'a> PuzzleSearch<'a> {
|
|||||||
let VarToken(replace) = to;
|
let VarToken(replace) = to;
|
||||||
|
|
||||||
// Create new constraints to reflect the unification.
|
// Create new constraints to reflect the unification.
|
||||||
let new_constraints = try!(self.constraints.substitute(from, to));
|
let new_constraints = r#try!(self.constraints.substitute(from, to));
|
||||||
self.constraints = Rc::new(new_constraints);
|
self.constraints = Rc::new(new_constraints);
|
||||||
self.wake.union_with(&self.constraints.wake[replace]);
|
self.wake.union_with(&self.constraints.wake[replace]);
|
||||||
assert!(self.constraints.wake[search].is_empty());
|
assert!(self.constraints.wake[search].is_empty());
|
||||||
|
|
||||||
// Take intersection of the candidates.
|
// Take intersection of the candidates.
|
||||||
if let &VarState::Assigned(val) = &self.vars[search] {
|
if let &VarState::Assigned(val) = &self.vars[search] {
|
||||||
try!(self.set_candidate(to, val));
|
r#try!(self.set_candidate(to, val));
|
||||||
} else {
|
} else {
|
||||||
if let (&mut VarState::Unassigned(Candidates::Set(ref mut rc1)),
|
if let (&mut VarState::Unassigned(Candidates::Set(ref mut rc1)),
|
||||||
&mut VarState::Unassigned(Candidates::Set(ref mut rc2)))
|
&mut VarState::Unassigned(Candidates::Set(ref mut rc2)))
|
||||||
@ -905,7 +905,7 @@ fn get_two_mut<'a, T>(slice: &'a mut [T], a: usize, b: usize)
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use ::Puzzle;
|
use crate::Puzzle;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_no_vars() {
|
fn test_no_vars() {
|
||||||
|
@ -140,7 +140,7 @@ impl Nonogram {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Constraint for Nonogram {
|
impl Constraint for Nonogram {
|
||||||
fn vars<'a>(&'a self) -> Box<Iterator<Item=&'a VarToken> + 'a> {
|
fn vars<'a>(&'a self) -> Box<dyn Iterator<Item=&'a VarToken> + 'a> {
|
||||||
Box::new(self.vars.iter())
|
Box::new(self.vars.iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,9 +162,9 @@ impl Constraint for Nonogram {
|
|||||||
AutoFillResult::SolutionFound =>
|
AutoFillResult::SolutionFound =>
|
||||||
for idx in 0..self.vars.len() {
|
for idx in 0..self.vars.len() {
|
||||||
if accum[idx] == FLAG_UNKNOWN | FLAG_OFF {
|
if accum[idx] == FLAG_UNKNOWN | FLAG_OFF {
|
||||||
try!(search.set_candidate(self.vars[idx], 0));
|
r#try!(search.set_candidate(self.vars[idx], 0));
|
||||||
} else if accum[idx] == FLAG_UNKNOWN | FLAG_ON {
|
} else if accum[idx] == FLAG_UNKNOWN | FLAG_ON {
|
||||||
try!(search.set_candidate(self.vars[idx], 1));
|
r#try!(search.set_candidate(self.vars[idx], 1));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -173,7 +173,7 @@ impl Constraint for Nonogram {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn substitute(&self, _search: VarToken, _replace: VarToken)
|
fn substitute(&self, _search: VarToken, _replace: VarToken)
|
||||||
-> PsResult<Rc<Constraint>> {
|
-> PsResult<Rc<dyn Constraint>> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ struct NoDiagonal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Constraint for NoDiagonal {
|
impl Constraint for NoDiagonal {
|
||||||
fn vars<'a>(&'a self) -> Box<Iterator<Item=&'a VarToken> + 'a> {
|
fn vars<'a>(&'a self) -> Box<dyn Iterator<Item=&'a VarToken> + 'a> {
|
||||||
Box::new(self.vars.iter())
|
Box::new(self.vars.iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,8 +23,8 @@ impl Constraint for NoDiagonal {
|
|||||||
if !search.is_assigned(var2) {
|
if !search.is_assigned(var2) {
|
||||||
let x1 = val;
|
let x1 = val;
|
||||||
let dy = (y1 as Val) - (y2 as Val);
|
let dy = (y1 as Val) - (y2 as Val);
|
||||||
try!(search.remove_candidate(var2, x1 - dy));
|
r#try!(search.remove_candidate(var2, x1 - dy));
|
||||||
try!(search.remove_candidate(var2, x1 + dy));
|
r#try!(search.remove_candidate(var2, x1 + dy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ impl Constraint for NoDiagonal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn substitute(&self, _from: VarToken, _to: VarToken)
|
fn substitute(&self, _from: VarToken, _to: VarToken)
|
||||||
-> PsResult<Rc<Constraint>> {
|
-> PsResult<Rc<dyn Constraint>> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ struct BinaryRepr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Constraint for BinaryRepr {
|
impl Constraint for BinaryRepr {
|
||||||
fn vars<'a>(&'a self) -> Box<Iterator<Item=&'a VarToken> + 'a> {
|
fn vars<'a>(&'a self) -> Box<dyn Iterator<Item=&'a VarToken> + 'a> {
|
||||||
Box::new(iter::once(&self.value).chain(&self.bits))
|
Box::new(iter::once(&self.value).chain(&self.bits))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ impl Constraint for BinaryRepr {
|
|||||||
if var == self.value {
|
if var == self.value {
|
||||||
let mut val = val;
|
let mut val = val;
|
||||||
for &var in self.bits.iter() {
|
for &var in self.bits.iter() {
|
||||||
try!(search.set_candidate(var, val & 1));
|
r#try!(search.set_candidate(var, val & 1));
|
||||||
val = val >> 1;
|
val = val >> 1;
|
||||||
}
|
}
|
||||||
} else if let Some(bitpos) = self.bits.iter().position(|&v| v == var) {
|
} else if let Some(bitpos) = self.bits.iter().position(|&v| v == var) {
|
||||||
@ -38,7 +38,7 @@ impl Constraint for BinaryRepr {
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
for c in discard.into_iter() {
|
for c in discard.into_iter() {
|
||||||
try!(search.remove_candidate(self.value, c));
|
r#try!(search.remove_candidate(self.value, c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ impl Constraint for BinaryRepr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn substitute(&self, _from: VarToken, _to: VarToken)
|
fn substitute(&self, _from: VarToken, _to: VarToken)
|
||||||
-> PsResult<Rc<Constraint>> {
|
-> PsResult<Rc<dyn Constraint>> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ enum Pet { Bird, Cat, Dog, Fish, Horse }
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn zebra() {
|
fn zebra() {
|
||||||
use Nat::*; use Col::*; use Dri::*; use Smo::*; use Pet::*;
|
use crate::Nat::*; use crate::Col::*; use crate::Dri::*; use crate::Smo::*; use crate::Pet::*;
|
||||||
|
|
||||||
// #1: There are five houses.
|
// #1: There are five houses.
|
||||||
let mut sys = Puzzle::new();
|
let mut sys = Puzzle::new();
|
||||||
|
Loading…
Reference in New Issue
Block a user