From 8e62c85bf5d1d202727735a570120bf3e6fb8227 Mon Sep 17 00:00:00 2001 From: David Wang Date: Thu, 2 Mar 2017 08:39:22 +1100 Subject: [PATCH] Add test: Zebra puzzle (A.K.A. Einstein's riddle). zebra: 453 guesses. --- tests/zebra.rs | 117 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 tests/zebra.rs diff --git a/tests/zebra.rs b/tests/zebra.rs new file mode 100644 index 0000000..5d11f52 --- /dev/null +++ b/tests/zebra.rs @@ -0,0 +1,117 @@ +//! Zebra puzzle (A.K.A. Einstein's riddle). +//! +//! https://en.wikipedia.org/wiki/Zebra_Puzzle +//! https://rosettacode.org/wiki/Zebra_puzzle + +#![allow(non_upper_case_globals)] + +extern crate puzzle_solver; + +use puzzle_solver::Puzzle; + +#[derive(Clone,Copy,Debug)] +enum Nat { Dane, Englishman, German, Norwegian, Swede } + +#[derive(Clone,Copy,Debug)] +enum Col { Blue, Green, Red, White, Yellow } + +#[derive(Clone,Copy,Debug)] +enum Dri { Beer, Coffee, Milk, Tea, Water } + +#[derive(Clone,Copy,Debug)] +enum Smo { Blend, BlueMaster, Dunhill, PallMall, Prince } + +#[derive(Clone,Copy,Debug)] +enum Pet { Bird, Cat, Dog, Fish, Horse } + +#[test] +fn zebra() { + use Nat::*; use Col::*; use Dri::*; use Smo::*; use Pet::*; + + // #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 = |n| nat_var[n as usize]; + let col = |n| col_var[n as usize]; + let dri = |n| dri_var[n as usize]; + let smo = |n| smo_var[n as usize]; + let pet = |n| pet_var[n as usize]; + + sys.all_different(&nat_var); + sys.all_different(&col_var); + sys.all_different(&dri_var); + sys.all_different(&smo_var); + sys.all_different(&pet_var); + + // #2: The Englishman lives in the red house. + sys.equals(nat(Englishman), col(Red)); + + // #3: The Swede has a dog. + sys.equals(nat(Swede), pet(Dog)); + + // #4: The Dane drinks tea. + sys.equals(nat(Dane), dri(Tea)); + + // #5: The green house is immediately to the left of the white house. + sys.equals(col(Green), col(White) - 1); + + // #6: They drink coffee in the green house. + sys.equals(dri(Coffee), col(Green)); + + // #7: The man who smokes Pall Mall has birds. + sys.equals(smo(PallMall), pet(Bird)); + + // #8: In the yellow house they smoke Dunhill. + sys.equals(col(Yellow), smo(Dunhill)); + + // #9: In the middle house they drink milk. + sys.equals(dri(Milk), 3); + + // #10: The Norwegian lives in the first house. + 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]); + 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]); + sys.equals(pet(Horse), smo(Dunhill) + neighbour12); + + // #13: The man who smokes Blue Master drinks beer. + sys.equals(smo(BlueMaster), dri(Beer)); + + // #14: The German smokes Prince. + sys.equals(nat(German), smo(Prince)); + + // #15: The Norwegian lives next to the blue house. + let neighbour15 = sys.new_var_with_candidates(&[-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]); + sys.equals(dri(Water), smo(Blend) + neighbour16); + + let dict = sys.solve_any().expect("solution"); + + let expected = [ + (Norwegian, Yellow, Water, Dunhill, Cat), + (Dane, Blue, Tea, Blend, Horse), + (Englishman, Red, Milk, PallMall, Bird), + (German, Green, Coffee, Prince, Fish), + (Swede, White, Beer, BlueMaster, Dog) ]; + + for &(n,c,d,s,p) in expected.iter() { + assert_eq!(dict[nat(n)], dict[col(c)]); + assert_eq!(dict[nat(n)], dict[dri(d)]); + assert_eq!(dict[nat(n)], dict[smo(s)]); + assert_eq!(dict[nat(n)], dict[pet(p)]); + } + + println!("zebra: {} guesses", sys.num_guesses()); +}