From 656890c1be58f3c86167134368e73c17478b3563 Mon Sep 17 00:00:00 2001 From: Andrey Tkachenko Date: Fri, 10 Dec 2021 13:20:36 +0400 Subject: [PATCH] Refactored variable constructors --- src/constraint/alldifferent.rs | 26 ++--- src/constraint/equality.rs | 14 +-- src/constraint/unify.rs | 20 ++-- src/linexpr.rs | 8 +- src/puzzle.rs | 196 ++++++++++++++++----------------- src/ranges.rs | 24 +--- tests/hidato.rs | 4 +- tests/kakuro.rs | 2 +- tests/killersudoku.rs | 2 +- tests/magicsquare.rs | 14 +-- tests/nonogram.rs | 2 +- tests/queens.rs | 2 +- tests/samuraisudoku.rs | 2 +- tests/sendmoremoney.rs | 12 +- tests/sudoku.rs | 2 +- tests/sujiko.rs | 2 +- tests/takuzu.rs | 10 +- tests/xkcd.rs | 4 +- tests/zebra.rs | 18 +-- 19 files changed, 174 insertions(+), 190 deletions(-) diff --git a/src/constraint/alldifferent.rs b/src/constraint/alldifferent.rs index 624dc71..ee3726c 100644 --- a/src/constraint/alldifferent.rs +++ b/src/constraint/alldifferent.rs @@ -17,7 +17,7 @@ impl AllDifferent { /// /// ``` /// let mut send_more_money = puzzle_solver::Puzzle::new(); - /// let vars = send_more_money.new_vars_with_candidates_1d(8, + /// let vars = send_more_money.new_vars(8, /// &[0,1,2,3,4,5,6,7,8,9]); /// /// puzzle_solver::constraint::AllDifferent::new(&vars); @@ -103,9 +103,9 @@ mod tests { #[test] fn test_contradiction() { let mut puzzle = Puzzle::new(); - let v0 = puzzle.new_var_with_candidates(&[1]); - let v1 = puzzle.new_var_with_candidates(&[1]); - let v2 = puzzle.new_var_with_candidates(&[1, 2, 3]); + let v0 = puzzle.new_var(&[1]); + let v1 = puzzle.new_var(&[1]); + let v2 = puzzle.new_var(&[1, 2, 3]); puzzle.all_different(&[v0, v1, v2]); @@ -116,9 +116,9 @@ mod tests { #[test] fn test_elimination() { let mut puzzle = Puzzle::new(); - let v0 = puzzle.new_var_with_candidates(&[1]); - let v1 = puzzle.new_var_with_candidates(&[1, 2, 3]); - let v2 = puzzle.new_var_with_candidates(&[1, 2, 3]); + let v0 = puzzle.new_var(&[1]); + let v1 = puzzle.new_var(&[1, 2, 3]); + let v2 = puzzle.new_var(&[1, 2, 3]); puzzle.all_different(&[v0, v1, v2]); @@ -131,9 +131,9 @@ mod tests { #[test] fn test_contradiction_by_length() { let mut puzzle = Puzzle::new(); - let v0 = puzzle.new_var_with_candidates(&[1, 2]); - let v1 = puzzle.new_var_with_candidates(&[1, 2]); - let v2 = puzzle.new_var_with_candidates(&[1, 2]); + let v0 = puzzle.new_var(&[1, 2]); + let v1 = puzzle.new_var(&[1, 2]); + let v2 = puzzle.new_var(&[1, 2]); puzzle.all_different(&[v0, v1, v2]); @@ -144,9 +144,9 @@ mod tests { #[test] fn test_constrain_by_value() { let mut puzzle = Puzzle::new(); - let v0 = puzzle.new_var_with_candidates(&[1, 2]); - let v1 = puzzle.new_var_with_candidates(&[1, 2]); - let v2 = puzzle.new_var_with_candidates(&[1, 2, 3]); + let v0 = puzzle.new_var(&[1, 2]); + let v1 = puzzle.new_var(&[1, 2]); + let v2 = puzzle.new_var(&[1, 2, 3]); puzzle.all_different(&[v0, v1, v2]); diff --git a/src/constraint/equality.rs b/src/constraint/equality.rs index 99f079d..9fd2099 100644 --- a/src/constraint/equality.rs +++ b/src/constraint/equality.rs @@ -19,7 +19,7 @@ impl Equality { /// /// ``` /// let mut magic_square = puzzle_solver::Puzzle::new(); - /// let vars = magic_square.new_vars_with_candidates_2d(3, 3, + /// let vars = magic_square.new_vars_2d(3, 3, /// &[1,2,3,4,5,6,7,8,9]); /// /// puzzle_solver::constraint::Equality::new( @@ -157,8 +157,8 @@ mod tests { #[test] fn test_contradiction() { let mut puzzle = Puzzle::new(); - let v0 = puzzle.new_var_with_candidates(&[3]); - let v1 = puzzle.new_var_with_candidates(&[0, 1]); + let v0 = puzzle.new_var(&[3]); + let v1 = puzzle.new_var(&[0, 1]); puzzle.equals(v0 + 2 * v1, 4); @@ -169,8 +169,8 @@ mod tests { #[test] fn test_assign() { let mut puzzle = Puzzle::new(); - let v0 = puzzle.new_var_with_candidates(&[1]); - let v1 = puzzle.new_var_with_candidates(&[1, 2, 3]); + let v0 = puzzle.new_var(&[1]); + let v1 = puzzle.new_var(&[1, 2, 3]); puzzle.equals(v0 + v1, 4); @@ -182,8 +182,8 @@ mod tests { #[test] fn test_reduce_range() { let mut puzzle = Puzzle::new(); - let v0 = puzzle.new_var_with_candidates(&[1, 2, 3]); - let v1 = puzzle.new_var_with_candidates(&[3, 4, 5]); + let v0 = puzzle.new_var(&[1, 2, 3]); + let v1 = puzzle.new_var(&[3, 4, 5]); puzzle.equals(v0 + v1, 5); diff --git a/src/constraint/unify.rs b/src/constraint/unify.rs index 9012b72..2cf71f3 100644 --- a/src/constraint/unify.rs +++ b/src/constraint/unify.rs @@ -18,8 +18,8 @@ impl Unify { /// /// ``` /// let mut send_more_money = puzzle_solver::Puzzle::new(); - /// let carry = send_more_money.new_vars_with_candidates_1d(4, &[0,1]); - /// let vars = send_more_money.new_vars_with_candidates_1d(8, + /// let carry = send_more_money.new_vars(4, &[0,1]); + /// let vars = send_more_money.new_vars(8, /// &[0,1,2,3,4,5,6,7,8,9]); /// /// let m = vars[4]; @@ -65,8 +65,8 @@ mod tests { #[test] fn test_unify_alldifferent() { let mut puzzle = Puzzle::new(); - let v0 = puzzle.new_var_with_candidates(&[1, 2]); - let v1 = puzzle.new_var_with_candidates(&[1, 2]); + let v0 = puzzle.new_var(&[1, 2]); + let v1 = puzzle.new_var(&[1, 2]); puzzle.all_different(&[v0, v1]); puzzle.unify(v0, v1); @@ -78,9 +78,9 @@ mod tests { #[test] fn test_unify_equality() { let mut puzzle = Puzzle::new(); - let v0 = puzzle.new_var_with_candidates(&[1, 2, 3, 4]); - let v1 = puzzle.new_var_with_candidates(&[1, 2, 3, 4]); - let v2 = puzzle.new_var_with_candidates(&[1, 2, 3, 4]); + let v0 = puzzle.new_var(&[1, 2, 3, 4]); + let v1 = puzzle.new_var(&[1, 2, 3, 4]); + let v2 = puzzle.new_var(&[1, 2, 3, 4]); puzzle.equals(v0 + 2 * v1 + v2, 6); puzzle.unify(v0, v1); @@ -94,9 +94,9 @@ mod tests { #[test] fn test_unify_unify() { let mut puzzle = Puzzle::new(); - let v0 = puzzle.new_var_with_candidates(&[1]); - let v1 = puzzle.new_var_with_candidates(&[1, 2, 3, 4]); - let v2 = puzzle.new_var_with_candidates(&[1, 2, 3, 4]); + let v0 = puzzle.new_var(&[1]); + let v1 = puzzle.new_var(&[1, 2, 3, 4]); + let v2 = puzzle.new_var(&[1, 2, 3, 4]); puzzle.unify(v0, v1); puzzle.unify(v1, v2); diff --git a/src/linexpr.rs b/src/linexpr.rs index 2ab1a58..f60ac54 100644 --- a/src/linexpr.rs +++ b/src/linexpr.rs @@ -279,8 +279,8 @@ mod tests { #[allow(clippy::identity_op, clippy::eq_op)] fn test_ops() { let mut puzzle = Puzzle::new(); - let x = puzzle.new_var_with_range(10..=10); - let y = puzzle.new_var_with_range(10..=10); + let x = puzzle.new_var(10..=10); + let y = puzzle.new_var(10..=10); // expr = var + const; let _ = x + 1; @@ -337,8 +337,8 @@ mod tests { #[allow(clippy::erasing_op, clippy::eq_op)] fn test_coef_zero() { let mut puzzle = Puzzle::new(); - let x = puzzle.new_var_with_range(10..10); - let y = puzzle.new_var_with_range(10..10); + let x = puzzle.new_var(10..10); + let y = puzzle.new_var(10..10); let expr = x * 0; assert_eq!(expr.coef.len(), 0); diff --git a/src/puzzle.rs b/src/puzzle.rs index dc745ba..1092f92 100644 --- a/src/puzzle.rs +++ b/src/puzzle.rs @@ -7,7 +7,9 @@ use std::fmt; use std::iter; use std::mem; use std::ops; +use std::ops::Bound; use std::ops::RangeBounds; +use std::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive}; use std::rc::Rc; use crate::constraint; @@ -18,12 +20,84 @@ use crate::{Constraint, PsResult, Solution, Val, VarToken}; /// A collection of candidates. #[derive(Clone, Debug, Eq, PartialEq)] -enum Candidates { +pub enum Candidates { Value(Val), // A variable set to its initial value. Set(Rc>), // A variable with a list of candidates. Range(Ranges), // A variable with candidate ranges. } +impl From for Candidates { + fn from(val: Val) -> Self { + Candidates::Value(val) + } +} + +impl From<&[Val]> for Candidates { + fn from(set: &[Val]) -> Self { + Candidates::Set(Rc::new(set.iter().copied().collect())) + } +} + +impl From<&[Val; N]> for Candidates { + fn from(set: &[Val; N]) -> Self { + Candidates::Set(Rc::new(set.iter().copied().collect())) + } +} + +impl From<[Val; N]> for Candidates { + fn from(set: [Val; N]) -> Self { + Candidates::Set(Rc::new(set.into_iter().collect())) + } +} + +impl From> for Candidates { + fn from(set: Vec) -> Self { + Candidates::Set(Rc::new(set.into_iter().collect())) + } +} + +impl From> for Candidates { + fn from(range: Range) -> Self { + Candidates::Range(range.into()) + } +} + +impl From> for Candidates { + fn from(range: RangeFrom) -> Self { + Candidates::Range(range.into()) + } +} + +impl From> for Candidates { + fn from(range: RangeTo) -> Self { + Candidates::Range(range.into()) + } +} + +impl From> for Candidates { + fn from(range: RangeInclusive) -> Self { + Candidates::Range(range.into()) + } +} + +impl From> for Candidates { + fn from(range: RangeToInclusive) -> Self { + Candidates::Range(range.into()) + } +} + +impl From for Candidates { + fn from(range: RangeFull) -> Self { + Candidates::Range(range.into()) + } +} + +impl From<(Bound, Bound)> for Candidates { + fn from(range: (Bound, Bound)) -> Self { + Candidates::Range(range.into()) + } +} + /// The state of a variable during the solution search. #[derive(Clone, Debug)] enum VarState { @@ -110,44 +184,13 @@ impl Puzzle { } } - fn new_var(&mut self, candidates: Candidates) -> VarToken { + pub fn new_var>(&mut self, candidates: C) -> VarToken { let var = VarToken(self.num_vars); self.num_vars += 1; - self.candidates.push(candidates); + self.candidates.push(candidates.into()); var } - /// Allocate a new puzzle variable, initialising it with potential - /// candidates. - /// - /// # Examples - /// - /// ``` - /// let mut send_more_money = puzzle_solver::Puzzle::new(); - /// send_more_money.new_var_with_candidates(&[0,1,2,3,4,5,6,7,8,9]); - /// ``` - pub fn new_var_with_candidates(&mut self, candidates: &[Val]) -> VarToken { - self.new_var(Candidates::Set(Rc::new(BTreeSet::from_iter( - candidates.iter().copied(), - )))) - } - - /// Allocate a new puzzle variable, initialising it with potential - /// candidates. - /// - /// # Examples - /// - /// ``` - /// let mut send_more_money = puzzle_solver::Puzzle::new(); - /// send_more_money.new_var_with_candidates(&[0,1,2,3,4,5,6,7,8,9]); - /// ``` - pub fn new_var_with_range>(&mut self, range: R) -> VarToken { - self.new_var(Candidates::Range(Ranges::new( - range.start_bound().cloned(), - range.end_bound().cloned(), - ))) - } - /// Allocate a 1d vector of puzzle variables, each initialised to /// have the same set of potential candidates. /// @@ -155,33 +198,12 @@ impl Puzzle { /// /// ``` /// let mut send_more_money = puzzle_solver::Puzzle::new(); - /// send_more_money.new_vars_with_candidates_1d(8, &[0,1,2,3,4,5,6,7,8,9]); + /// send_more_money.new_vars(8, &[0,1,2,3,4,5,6,7,8,9]); /// ``` - pub fn new_vars_with_candidates_1d(&mut self, n: usize, candidates: &[Val]) -> Vec { + pub fn new_vars + Clone>(&mut self, n: usize, candidates: C) -> Vec { let mut vars = Vec::with_capacity(n); for _ in 0..n { - vars.push(self.new_var_with_candidates(candidates)); - } - vars - } - - /// Allocate a 1d vector of puzzle variables, each initialised to - /// have the same set of potential candidates. - /// - /// # Examples - /// - /// ``` - /// let mut send_more_money = puzzle_solver::Puzzle::new(); - /// send_more_money.new_vars_with_candidates_1d(8, &[0,1,2,3,4,5,6,7,8,9]); - /// ``` - pub fn new_vars_with_range_1d + Clone>( - &mut self, - n: usize, - range: R, - ) -> Vec { - let mut vars = Vec::with_capacity(n); - for _ in 0..n { - vars.push(self.new_var_with_range(range.clone())); + vars.push(self.new_var(candidates.clone())); } vars } @@ -193,39 +215,17 @@ impl Puzzle { /// /// ``` /// let mut magic_square = puzzle_solver::Puzzle::new(); - /// magic_square.new_vars_with_candidates_2d(3, 3, &[1,2,3,4,5,6,7,8,9]); + /// magic_square.new_vars_2d(3, 3, &[1,2,3,4,5,6,7,8,9]); /// ``` - pub fn new_vars_with_candidates_2d( + pub fn new_vars_2d + Clone>( self: &mut Puzzle, width: usize, height: usize, - candidates: &[Val], + candidates: C, ) -> Vec> { let mut vars = Vec::with_capacity(height); for _ in 0..height { - vars.push(self.new_vars_with_candidates_1d(width, candidates)); - } - vars - } - - /// Allocate a 2d array of puzzle variables, each initialised to - /// have the same set of potential candidates. - /// - /// # Examples - /// - /// ``` - /// let mut magic_square = puzzle_solver::Puzzle::new(); - /// magic_square.new_vars_with_candidates_2d(3, 3, &[1,2,3,4,5,6,7,8,9]); - /// ``` - pub fn new_vars_with_range_2d + Clone>( - self: &mut Puzzle, - width: usize, - height: usize, - range: R, - ) -> Vec> { - let mut vars = Vec::with_capacity(height); - for _ in 0..height { - vars.push(self.new_vars_with_range_1d(width, range.clone())); + vars.push(self.new_vars(width, candidates.clone())); } vars } @@ -240,7 +240,7 @@ impl Puzzle { /// /// ``` /// let mut magic_square = puzzle_solver::Puzzle::new(); - /// let vars = magic_square.new_vars_with_candidates_2d(3, 3, + /// let vars = magic_square.new_vars_2d(3, 3, /// &[1,2,3,4,5,6,7,8,9]); /// /// magic_square.set_value(vars[1][1], 5); @@ -264,7 +264,7 @@ impl Puzzle { /// ``` /// let mut send_more_money = puzzle_solver::Puzzle::new(); /// for _ in 0..9 { - /// let var = send_more_money.new_var(); + /// let var = send_more_money.new_var([]); /// send_more_money.insert_candidates(var, &[0,1,2,3,4,5,6,7,8,9]); /// } /// ``` @@ -289,7 +289,7 @@ impl Puzzle { /// /// ``` /// let mut send_more_money = puzzle_solver::Puzzle::new(); - /// let vars = send_more_money.new_vars_with_candidates_1d(8, + /// let vars = send_more_money.new_vars(8, /// &[0,1,2,3,4,5,6,7,8,9]); /// /// let s = vars[0]; @@ -319,7 +319,7 @@ impl Puzzle { /// /// ``` /// let mut send_more_money = puzzle_solver::Puzzle::new(); - /// let vars = send_more_money.new_vars_with_candidates_1d(8, + /// let vars = send_more_money.new_vars(8, /// &[0,1,2,3,4,5,6,7,8,9]); /// /// let m = vars[4]; @@ -370,7 +370,7 @@ impl Puzzle { /// /// ``` /// let mut send_more_money = puzzle_solver::Puzzle::new(); - /// let vars = send_more_money.new_vars_with_candidates_1d(8, + /// let vars = send_more_money.new_vars(8, /// &[0,1,2,3,4,5,6,7,8,9]); /// /// send_more_money.all_different(&vars); @@ -388,7 +388,7 @@ impl Puzzle { /// /// ``` /// let mut magic_square = puzzle_solver::Puzzle::new(); - /// let vars = magic_square.new_vars_with_candidates_2d(3, 3, + /// let vars = magic_square.new_vars_2d(3, 3, /// &[1,2,3,4,5,6,7,8,9]); /// /// magic_square.equals(vars[0][0] + vars[0][1] + vars[0][2], 15); @@ -407,8 +407,8 @@ impl Puzzle { /// /// ``` /// let mut send_more_money = puzzle_solver::Puzzle::new(); - /// let carry = send_more_money.new_vars_with_candidates_1d(4, &[0,1]); - /// let vars = send_more_money.new_vars_with_candidates_1d(8, + /// let carry = send_more_money.new_vars(4, &[0,1]); + /// let vars = send_more_money.new_vars(8, /// &[0,1,2,3,4,5,6,7,8,9]); /// /// let m = vars[4]; @@ -424,8 +424,8 @@ impl Puzzle { /// /// ``` /// let mut puzzle = puzzle_solver::Puzzle::new(); - /// puzzle.new_var_with_candidates(&[1,2]); - /// puzzle.new_var_with_candidates(&[3,4]); + /// puzzle.new_var(&[1,2]); + /// puzzle.new_var(&[3,4]); /// /// let solution = puzzle.solve_any(); /// assert!(solution.is_some()); @@ -449,8 +449,8 @@ impl Puzzle { /// /// ``` /// let mut puzzle = puzzle_solver::Puzzle::new(); - /// puzzle.new_var_with_candidates(&[1,2]); - /// puzzle.new_var_with_candidates(&[3,4]); + /// puzzle.new_var(&[1,2]); + /// puzzle.new_var(&[3,4]); /// /// let solution = puzzle.solve_unique(); /// assert!(solution.is_none()); @@ -475,8 +475,8 @@ impl Puzzle { /// /// ``` /// let mut puzzle = puzzle_solver::Puzzle::new(); - /// puzzle.new_var_with_candidates(&[1,2]); - /// puzzle.new_var_with_candidates(&[3,4]); + /// puzzle.new_var(&[1,2]); + /// puzzle.new_var(&[3,4]); /// /// let solutions = puzzle.solve_all(); /// assert_eq!(solutions.len(), 4); diff --git a/src/ranges.rs b/src/ranges.rs index f1ffc1a..bb5d0c1 100644 --- a/src/ranges.rs +++ b/src/ranges.rs @@ -1,7 +1,5 @@ -use std::ops::{Bound, Range, RangeBounds, RangeInclusive}; - +use std::ops::{Bound, RangeBounds}; use ranges::GenericRange; - use crate::Val; #[derive(Clone, Debug, Eq, PartialEq)] @@ -96,24 +94,8 @@ impl Ranges { } } -impl From<(Bound, Bound)> for Ranges { - fn from(range: (Bound, Bound)) -> Self { - Self { - inner: range.into(), - } - } -} - -impl From> for Ranges { - fn from(range: RangeInclusive) -> Self { - Self { - inner: range.into(), - } - } -} - -impl From> for Ranges { - fn from(range: Range) -> Self { +impl>> From for Ranges { + fn from(range: T) -> Self { Self { inner: range.into(), } diff --git a/tests/hidato.rs b/tests/hidato.rs index 783ca29..76c1a7b 100644 --- a/tests/hidato.rs +++ b/tests/hidato.rs @@ -25,7 +25,7 @@ fn make_hidato(board: &Board) -> (Puzzle, Vec) { } } - let vars = sys.new_vars_with_candidates_1d(count, &pos); + let vars = sys.new_vars(count, pos); for y in 0..HEIGHT { for x in 0..WIDTH { @@ -51,7 +51,7 @@ fn make_hidato(board: &Board) -> (Puzzle, Vec) { ]; for i in 1..vars.len() { - let step = sys.new_var_with_candidates(&deltas); + let step = sys.new_var(&deltas); sys.equals(vars[i], vars[i - 1] + step); } diff --git a/tests/kakuro.rs b/tests/kakuro.rs index 2c9e915..c45dc11 100644 --- a/tests/kakuro.rs +++ b/tests/kakuro.rs @@ -40,7 +40,7 @@ fn make_kakuro(board: &[Rule]) -> (Puzzle, KakuroVars) { for y in y1..(y2 + 1) { for x in x1..(x2 + 1) { let var = vars[y][x].unwrap_or_else(|| { - let var = sys.new_var_with_candidates(&[1, 2, 3, 4, 5, 6, 7, 8, 9]); + let var = sys.new_var(&[1, 2, 3, 4, 5, 6, 7, 8, 9]); vars[y][x] = Some(var); var }); diff --git a/tests/killersudoku.rs b/tests/killersudoku.rs index 7d3fe56..0c3db76 100644 --- a/tests/killersudoku.rs +++ b/tests/killersudoku.rs @@ -13,7 +13,7 @@ type Point = (usize, usize); fn make_killer_sudoku(board: &[(Val, Vec)]) -> (Puzzle, Vec>) { let mut sys = Puzzle::new(); - let vars = sys.new_vars_with_candidates_2d(SIZE, SIZE, &[1, 2, 3, 4, 5, 6, 7, 8, 9]); + let vars = sys.new_vars_2d(SIZE, SIZE, &[1, 2, 3, 4, 5, 6, 7, 8, 9]); for y in 0..SIZE { sys.all_different(&vars[y]); diff --git a/tests/magicsquare.rs b/tests/magicsquare.rs index 2ab2197..c990f71 100644 --- a/tests/magicsquare.rs +++ b/tests/magicsquare.rs @@ -2,19 +2,17 @@ //! //! https://en.wikipedia.org/wiki/Magic_square -extern crate puzzle_solver; - use puzzle_solver::{LinExpr, Puzzle, Solution, Val, VarToken}; fn make_magic_square(n: usize) -> (Puzzle, Vec>, VarToken) { let mut sys = Puzzle::new(); - let digits: Vec = (1..(n * n + 1) as Val).collect(); - let vars = sys.new_vars_with_candidates_2d(n, n, &digits); + let digits = 1..(n * n + 1) as Val; + let vars = sys.new_vars_2d(n, n, digits.clone()); // Calculate the range of the total (in a dumb way). - let min = digits.iter().take(n).sum(); - let max = digits.iter().rev().take(n).sum(); - let total = sys.new_var_with_candidates(&(min..max).collect::>()); + let min = digits.clone().into_iter().take(n).sum(); + let max = digits.clone().into_iter().rev().take(n).sum(); + let total = sys.new_var(min..max); sys.all_different(vars.iter().flatten()); @@ -44,7 +42,7 @@ fn make_magic_square(n: usize) -> (Puzzle, Vec>, VarToken) { } // Sum of all digits = sum of all rows (columns) = total * n. - sys.equals(total * (n as Val), digits.iter().sum::()); + sys.equals(total * (n as Val), digits.into_iter().sum::()); (sys, vars, total) } diff --git a/tests/nonogram.rs b/tests/nonogram.rs index 273465f..23fc12b 100644 --- a/tests/nonogram.rs +++ b/tests/nonogram.rs @@ -194,7 +194,7 @@ impl Constraint for Nonogram { fn make_nonogram(rows: &[Vec], cols: &[Vec]) -> (Puzzle, Vec>) { let mut sys = Puzzle::new(); let (w, h) = (cols.len(), rows.len()); - let vars = sys.new_vars_with_candidates_2d(w, h, &[0, 1]); + let vars = sys.new_vars_2d(w, h, &[0, 1]); for y in 0..h { sys.add_constraint(Nonogram::new(&vars[y], &rows[y])); diff --git a/tests/queens.rs b/tests/queens.rs index 317a264..980f8c8 100644 --- a/tests/queens.rs +++ b/tests/queens.rs @@ -43,7 +43,7 @@ impl Constraint for NoDiagonal { fn make_queens(n: usize) -> (Puzzle, Vec) { let mut sys = Puzzle::new(); let pos: Vec = (0..n as Val).collect(); - let vars = sys.new_vars_with_candidates_1d(n, &pos); + let vars = sys.new_vars(n, pos); sys.all_different(&vars); sys.add_constraint(NoDiagonal { vars: vars.clone() }); diff --git a/tests/samuraisudoku.rs b/tests/samuraisudoku.rs index 778bef7..704fa0a 100644 --- a/tests/samuraisudoku.rs +++ b/tests/samuraisudoku.rs @@ -15,7 +15,7 @@ type SudokuVars = Vec>; type SamuraiVars = (SudokuVars, SudokuVars, SudokuVars, SudokuVars, SudokuVars); fn make_sudoku(sys: &mut Puzzle) -> SudokuVars { - let vars = sys.new_vars_with_candidates_2d(SIZE, SIZE, &[1, 2, 3, 4, 5, 6, 7, 8, 9]); + let vars = sys.new_vars_2d(SIZE, SIZE, &[1, 2, 3, 4, 5, 6, 7, 8, 9]); for y in 0..SIZE { sys.all_different(&vars[y]); diff --git a/tests/sendmoremoney.rs b/tests/sendmoremoney.rs index f659a36..7dd125e 100644 --- a/tests/sendmoremoney.rs +++ b/tests/sendmoremoney.rs @@ -8,7 +8,8 @@ use puzzle_solver::{Puzzle, Solution, VarToken}; fn make_send_more_money() -> (Puzzle, Vec) { let mut sys = Puzzle::new(); - let vars = sys.new_vars_with_candidates_1d(8, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + let vars = sys.new_vars(8, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + let (s, e, n, d) = (vars[0], vars[1], vars[2], vars[3]); let (m, o, r, y) = (vars[4], vars[5], vars[6], vars[7]); @@ -20,6 +21,7 @@ fn make_send_more_money() -> (Puzzle, Vec) { let send = 1000 * s + 100 * e + 10 * n + d; let more = 1000 * m + 100 * o + 10 * r + e; let money = 10000 * m + 1000 * o + 100 * n + 10 * e + y; + sys.equals(send + more, money); (sys, vars) @@ -59,9 +61,11 @@ fn sendmoremoney_carry() { let (mut sys, vars) = make_send_more_money(); let (s, e, n, d) = (vars[0], vars[1], vars[2], vars[3]); let (m, o, r, y) = (vars[4], vars[5], vars[6], vars[7]); - let c1 = sys.new_var_with_candidates(&carry); - let c2 = sys.new_var_with_candidates(&carry); - let c3 = sys.new_var_with_candidates(&carry); + + let c1 = sys.new_var(&carry); + let c2 = sys.new_var(&carry); + let c3 = sys.new_var(&carry); + sys.intersect_candidates(m, &carry); // c4 == m. sys.equals(d + e, 10 * c1 + y); diff --git a/tests/sudoku.rs b/tests/sudoku.rs index 26e80d0..713a1df 100644 --- a/tests/sudoku.rs +++ b/tests/sudoku.rs @@ -12,7 +12,7 @@ type Board = [[Val; SIZE]; SIZE]; fn make_sudoku(board: &Board) -> (Puzzle, Vec>) { let mut sys = Puzzle::new(); - let vars = sys.new_vars_with_range_2d(SIZE, SIZE, 1..=9); + let vars = sys.new_vars_2d(SIZE, SIZE, 1..=9); for y in 0..SIZE { sys.all_different(&vars[y]); diff --git a/tests/sujiko.rs b/tests/sujiko.rs index 49120df..d00966e 100644 --- a/tests/sujiko.rs +++ b/tests/sujiko.rs @@ -12,7 +12,7 @@ type Board = [[Val; SIZE]; SIZE]; fn make_sujiko(board: &Board, tl: Val, tr: Val, bl: Val, br: Val) -> (Puzzle, Vec>) { let mut sys = Puzzle::new(); - let vars = sys.new_vars_with_candidates_2d(3, 3, &[1, 2, 3, 4, 5, 6, 7, 8, 9]); + let vars = sys.new_vars_2d(3, 3, &[1, 2, 3, 4, 5, 6, 7, 8, 9]); sys.all_different(vars.iter().flatten()); diff --git a/tests/takuzu.rs b/tests/takuzu.rs index 2c11ad9..e8b35db 100644 --- a/tests/takuzu.rs +++ b/tests/takuzu.rs @@ -82,9 +82,9 @@ fn make_takuzu(puzzle: &[Vec]) -> (Puzzle, Vec>) { let col_candidates = make_sums(width); let mut sys = Puzzle::new(); - let vars = sys.new_vars_with_candidates_2d(width, height, &[0, 1]); - let row_values = sys.new_vars_with_candidates_1d(height, &row_candidates); - let col_values = sys.new_vars_with_candidates_1d(width, &col_candidates); + let vars = sys.new_vars_2d(width, height, &[0, 1]); + let row_values = sys.new_vars(height, row_candidates); + let col_values = sys.new_vars(width, col_candidates); for y in 0..height { let total = (height as Val) / 2; @@ -113,14 +113,14 @@ fn make_takuzu(puzzle: &[Vec]) -> (Puzzle, Vec>) { // No three in a row, i.e. not: 000, 111. for y in 0..height { for window in vars[y].windows(3) { - let disjunction = sys.new_var_with_candidates(&[1, 2]); + let disjunction = sys.new_var(&[1, 2]); sys.equals(window[0] + window[1] + window[2], disjunction); } } for x in 0..width { for y in 0..(height - 2) { - let disjunction = sys.new_var_with_candidates(&[1, 2]); + let disjunction = sys.new_var(&[1, 2]); sys.equals( vars[y + 0][x] + vars[y + 1][x] + vars[y + 2][x], disjunction, diff --git a/tests/xkcd.rs b/tests/xkcd.rs index ab82b23..c25b075 100644 --- a/tests/xkcd.rs +++ b/tests/xkcd.rs @@ -9,7 +9,7 @@ extern crate puzzle_solver; use num_rational::Ratio; use num_traits::ToPrimitive; -use puzzle_solver::{LinExpr, Puzzle, Val}; +use puzzle_solver::{LinExpr, Puzzle}; #[test] fn xkcd_knapsack() { @@ -28,7 +28,7 @@ fn xkcd_knapsack() { for &(cost, _) in menu.iter() { let num = (total / cost).floor().to_integer(); - let var = sys.new_var_with_candidates(&(0..(num + 1)).collect::>()); + let var = sys.new_var(0..=num); vars.push(var) } diff --git a/tests/zebra.rs b/tests/zebra.rs index 300cb84..265fd9c 100644 --- a/tests/zebra.rs +++ b/tests/zebra.rs @@ -64,11 +64,11 @@ fn zebra() { // #1: There are five houses. let mut sys = Puzzle::new(); - let nat_var = sys.new_vars_with_candidates_1d(5, &[1, 2, 3, 4, 5]); - let col_var = sys.new_vars_with_candidates_1d(5, &[1, 2, 3, 4, 5]); - let dri_var = sys.new_vars_with_candidates_1d(5, &[1, 2, 3, 4, 5]); - let smo_var = sys.new_vars_with_candidates_1d(5, &[1, 2, 3, 4, 5]); - let pet_var = sys.new_vars_with_candidates_1d(5, &[1, 2, 3, 4, 5]); + let nat_var = sys.new_vars(5, &[1, 2, 3, 4, 5]); + let col_var = sys.new_vars(5, &[1, 2, 3, 4, 5]); + let dri_var = sys.new_vars(5, &[1, 2, 3, 4, 5]); + let smo_var = sys.new_vars(5, &[1, 2, 3, 4, 5]); + let pet_var = sys.new_vars(5, &[1, 2, 3, 4, 5]); let nat = |n| nat_var[n as usize]; let col = |n| col_var[n as usize]; @@ -110,11 +110,11 @@ fn zebra() { sys.equals(nat(Norwegian), 1); // #11: The man who smokes Blend lives in the house next to the house with cats. - let neighbour11 = sys.new_var_with_candidates(&[-1, 1]); + let neighbour11 = sys.new_var(&[-1, 1]); sys.equals(smo(Blend), pet(Cat) + neighbour11); // #12: In a house next to the house where they have a horse, they smoke Dunhill. - let neighbour12 = sys.new_var_with_candidates(&[-1, 1]); + let neighbour12 = sys.new_var(&[-1, 1]); sys.equals(pet(Horse), smo(Dunhill) + neighbour12); // #13: The man who smokes Blue Master drinks beer. @@ -124,11 +124,11 @@ fn zebra() { sys.equals(nat(German), smo(Prince)); // #15: The Norwegian lives next to the blue house. - let neighbour15 = sys.new_var_with_candidates(&[-1, 1]); + let neighbour15 = sys.new_var(&[-1, 1]); sys.equals(nat(Norwegian), col(Blue) + neighbour15); // #16: They drink water in a house next to the house where they smoke Blend. - let neighbour16 = sys.new_var_with_candidates(&[-1, 1]); + let neighbour16 = sys.new_var(&[-1, 1]); sys.equals(dri(Water), smo(Blend) + neighbour16); let dict = sys.solve_any().expect("solution");