From d9f92e2baa8847472828b018ab96a53970c2954b Mon Sep 17 00:00:00 2001 From: David Wang Date: Sat, 4 Mar 2017 07:57:26 +1100 Subject: [PATCH] Add test: Hidato. hidato_wikipedia: 4 guesses. --- tests/hidato.rs | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 tests/hidato.rs diff --git a/tests/hidato.rs b/tests/hidato.rs new file mode 100644 index 0000000..7f98b94 --- /dev/null +++ b/tests/hidato.rs @@ -0,0 +1,111 @@ +//! Hidato. +//! +//! https://en.wikipedia.org/wiki/Hidato + +extern crate puzzle_solver; + +use puzzle_solver::{Puzzle,Solution,Val,VarToken}; + +const WIDTH: usize = 8; +const HEIGHT: usize = 8; +const NA: i32 = -1; +type Board = [[i32; WIDTH]; HEIGHT]; + +fn make_hidato(board: &Board) -> (Puzzle, Vec) { + let mut sys = Puzzle::new(); + let mut pos = Vec::new(); + let mut count = 0; + + for y in 0..HEIGHT { + for x in 0..WIDTH { + if board[y][x] != NA { + pos.push((WIDTH * y + x) as Val); + count = count + 1; + } + } + } + + let vars = sys.new_vars_with_candidates_1d(count, &pos); + + for y in 0..HEIGHT { + for x in 0..WIDTH { + if board[y][x] > 0 { + let idx = (board[y][x] - 1) as usize; + sys.set_value(vars[idx], (WIDTH * y + x) as Val); + } + } + } + + sys.all_different(&vars); + + let stride = WIDTH as Val; + let deltas = [ + -stride - 1, -stride, -stride + 1, + -1, 1, + stride - 1, stride, stride + 1 ]; + + for i in 1..vars.len() { + let step = sys.new_var_with_candidates(&deltas); + sys.equals(vars[i], vars[i - 1] + step); + } + + (sys, vars) +} + +fn print_hidato(dict: &Solution, vars: &Vec) { + let mut board = [[NA; WIDTH]; HEIGHT]; + + for (idx, &var) in vars.iter().enumerate() { + let x = (dict[var] as usize) % WIDTH; + let y = (dict[var] as usize) / WIDTH; + board[y][x] = (idx as i32) + 1; + } + + for y in 0..HEIGHT { + for x in 0..WIDTH { + if board[y][x] == NA { + print!(" --"); + } else { + print!(" {:2}", board[y][x]); + } + } + println!(); + } +} + +fn verify_hidato(dict: &Solution, vars: &Vec, expected: &Board) { + for (idx, &var) in vars.iter().enumerate() { + let x = (dict[var] as usize) % WIDTH; + let y = (dict[var] as usize) / WIDTH; + assert_eq!((idx as i32) + 1, expected[y][x]); + } +} + +#[test] +fn hidato_wikipedia() { + let puzzle = [ + [ 0, 33, 35, 0, 0, NA, NA, NA ], + [ 0, 0, 24, 22, 0, NA, NA, NA ], + [ 0, 0, 0, 21, 0, 0, NA, NA ], + [ 0, 26, 0, 13, 40, 11, NA, NA ], + [ 27, 0, 0, 0, 9, 0, 1, NA ], + [ NA, NA, 0, 0, 18, 0, 0, NA ], + [ NA, NA, NA, NA, 0, 7, 0, 0 ], + [ NA, NA, NA, NA, NA, NA, 5, 0 ] ]; + + let expected = [ + [ 32, 33, 35, 36, 37, NA, NA, NA ], + [ 31, 34, 24, 22, 38, NA, NA, NA ], + [ 30, 25, 23, 21, 12, 39, NA, NA ], + [ 29, 26, 20, 13, 40, 11, NA, NA ], + [ 27, 28, 14, 19, 9, 10, 1, NA ], + [ NA, NA, 15, 16, 18, 8, 2, NA ], + [ NA, NA, NA, NA, 17, 7, 6, 3 ], + [ NA, NA, NA, NA, NA, NA, 5, 4 ] ]; + + let (mut sys, vars) = make_hidato(&puzzle); + let dict = sys.solve_any().expect("solution"); + print_hidato(&dict, &vars); + verify_hidato(&dict, &vars, &expected); + println!("hidato_wikipedia: {} guesses", sys.num_guesses()); +}