From 630f09fc80f4021af996a7ad712e9d7a258e5316 Mon Sep 17 00:00:00 2001 From: David Wang Date: Fri, 17 Mar 2017 08:32:30 +1100 Subject: [PATCH] Add test: xkcd knapsack problem. xkcd_knapsack: 60 guesses. --- tests/xkcd.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 tests/xkcd.rs diff --git a/tests/xkcd.rs b/tests/xkcd.rs new file mode 100644 index 0000000..9604833 --- /dev/null +++ b/tests/xkcd.rs @@ -0,0 +1,50 @@ +//! xkcd Knapsack Problem. +//! +//! https://en.wikipedia.org/wiki/Knapsack_problem +//! https://xkcd.com/287/ + +extern crate num_rational; +extern crate num_traits; +extern crate puzzle_solver; + +use num_rational::Ratio; +use num_traits::ToPrimitive; +use puzzle_solver::{LinExpr,Puzzle,Val}; + +#[test] +fn xkcd_knapsack() { + let menu = [ + (Ratio::new(2_15, 100), "Mixed Fruit"), + (Ratio::new(2_75, 100), "French Fries"), + (Ratio::new(3_35, 100), "Side Salad"), + (Ratio::new(3_55, 100), "Hot Wings"), + (Ratio::new(4_20, 100), "Mozzarella Sticks"), + (Ratio::new(5_80, 100), "Sampler Plate") ]; + + let mut sys = Puzzle::new(); + let mut vars = Vec::with_capacity(menu.len()); + let total = Ratio::new(15_05, 100); + + for &(cost, _) in menu.iter() { + let num = (total / cost).floor().to_integer(); + let var = sys.new_var_with_candidates(&(0..(num + 1)).collect::>()); + vars.push(var) + } + + sys.equals(total, vars.iter().zip(menu.iter()).fold(LinExpr::from(0), + |sum, (&var, &(cost, _))| sum + var * cost)); + + let solutions = sys.solve_all(); + assert_eq!(solutions.len(), 2); + + for dict in solutions.iter() { + println!(""); + for (&var, &(cost, string)) in vars.iter().zip(menu.iter()) { + let numer = cost.numer().to_f32().unwrap(); + let denom = cost.denom().to_f32().unwrap(); + println!(" {} x {:.2} {}", dict[var], numer / denom, string); + } + } + + println!("xkcd_knapsack: {} guesses", sys.num_guesses()); +}