From c93b9430c1e4ff96c65cc70f65b29a58c49641cf Mon Sep 17 00:00:00 2001 From: David Wang Date: Sat, 4 Mar 2017 08:22:07 +1100 Subject: [PATCH] Add test: Kakuro. kakuro_wikipedia: 9 guesses. --- tests/kakuro.rs | 105 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 tests/kakuro.rs diff --git a/tests/kakuro.rs b/tests/kakuro.rs new file mode 100644 index 0000000..84cec7f --- /dev/null +++ b/tests/kakuro.rs @@ -0,0 +1,105 @@ +//! Kakuro. +//! +//! https://en.wikipedia.org/wiki/Kakuro + +extern crate puzzle_solver; + +use puzzle_solver::{LinExpr,Puzzle,Solution,Val,VarToken}; + +const SIZE: usize = 7; +const X: Val = 0; +type Board = [[Val; SIZE]; SIZE]; +type KakuroVars = Vec>>; + +enum Rule { + H{ total: Val, y: usize, x1: usize, x2: usize }, + V{ total: Val, x: usize, y1: usize, y2: usize }, +} + +fn make_kakuro(board: &[Rule]) -> (Puzzle, KakuroVars) { + let mut sys = Puzzle::new(); + let mut vars = vec![vec![None; SIZE]; SIZE]; + + for rule in board.iter() { + let (total, x1, y1, x2, y2) = match rule { + &Rule::H{total, y, x1, x2} => (total, x1, y, x2, y), + &Rule::V{total, x, y1, y2} => (total, x, y1, x, y2), + }; + + let mut vec = Vec::new(); + 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]); + vars[y][x] = Some(var); + var + }); + + vec.push(var); + } + } + + sys.all_different(&vec); + sys.equals(total, vec.iter().fold(LinExpr::from(0), |sum, &var| sum + var)); + } + + (sys, vars) +} + +fn print_kakuro(dict: &Solution, vars: &KakuroVars) { + for y in 0..SIZE { + for x in 0..SIZE { + if let Some(var) = vars[y][x] { + print!(" {}", dict[var]); + } else { + print!(" ."); + } + } + println!(); + } +} + +fn verify_kakuro(dict: &Solution, vars: &KakuroVars, expected: &Board) { + for y in 0..SIZE { + for x in 0..SIZE { + let val = vars[y][x].map_or(X, |var| dict[var]); + assert_eq!(val, expected[y][x]); + } + } +} + +#[test] +fn kakuro_wikipedia() { + let puzzle = [ + Rule::H{ total:16, y:0, x1:0, x2:1 }, Rule::H{ total:24, y:0, x1:4, x2:6}, + Rule::H{ total:17, y:1, x1:0, x2:1 }, Rule::H{ total:29, y:1, x1:3, x2:6}, + Rule::H{ total:35, y:2, x1:0, x2:4 }, + Rule::H{ total: 7, y:3, x1:1, x2:2 }, Rule::H{ total: 8, y:3, x1:4, x2:5}, + Rule::H{ total:16, y:4, x1:2, x2:6 }, + Rule::H{ total:21, y:5, x1:0, x2:3 }, Rule::H{ total: 5, y:5, x1:5, x2:6}, + Rule::H{ total: 6, y:6, x1:0, x2:2 }, Rule::H{ total: 3, y:6, x1:5, x2:6}, + + Rule::V{ total:23, x:0, y1:0, y2:2 }, Rule::V{ total:11, x:0, y1:5, y2:6}, + Rule::V{ total:30, x:1, y1:0, y2:3 }, Rule::V{ total:10, x:1, y1:5, y2:6}, + Rule::V{ total:15, x:2, y1:2, y2:6 }, + Rule::V{ total:17, x:3, y1:1, y2:2 }, Rule::V{ total: 7, x:3, y1:4, y2:5}, + Rule::V{ total:27, x:4, y1:0, y2:4 }, + Rule::V{ total:12, x:5, y1:0, y2:1 }, Rule::V{ total:12, x:5, y1:3, y2:6}, + Rule::V{ total:16, x:6, y1:0, y2:1 }, Rule::V{ total: 7, x:6, y1:4, y2:6}, + ]; + + let expected = [ + [ 9, 7, X, X, 8, 7, 9 ], + [ 8, 9, X, 8, 9, 5, 7 ], + [ 6, 8, 5, 9, 7, X, X ], + [ X, 6, 1, X, 2, 6, X ], + [ X, X, 4, 6, 1, 3, 2 ], + [ 8, 9, 3, 1, X, 1, 4 ], + [ 3, 1, 2, X, X, 2, 1 ] ]; + + let (mut sys, vars) = make_kakuro(&puzzle); + let dict = sys.solve_any().expect("solution"); + print_kakuro(&dict, &vars); + verify_kakuro(&dict, &vars, &expected); + println!("kakuro_wikipedia: {} guesses", sys.num_guesses()); +}