Add test: xkcd knapsack problem.
xkcd_knapsack: 60 guesses.
This commit is contained in:
parent
3afb599568
commit
630f09fc80
50
tests/xkcd.rs
Normal file
50
tests/xkcd.rs
Normal file
@ -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::<Vec<Val>>());
|
||||
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());
|
||||
}
|
Loading…
Reference in New Issue
Block a user