Skip to content

Instantly share code, notes, and snippets.

@prakhar1989
Created September 13, 2014 17:26
Show Gist options
  • Save prakhar1989/11075d27f25537882d27 to your computer and use it in GitHub Desktop.
Save prakhar1989/11075d27f25537882d27 to your computer and use it in GitHub Desktop.
24 Game
// Implements http://rosettacode.org/wiki/24_game
// Uses RPN expression
use std::io;
use std::rand::{task_rng, Rng};
#[cfg(not(test))]
fn main() {
// generating 4 numbers
let mut rng = task_rng();
let choices: Vec<uint> = range(1u, 5).map(|_| rng.gen_range(1u, 10)).collect();
println!("Make 24 with the following numbers");
// start the game loop
loop {
print!("Your numbers: {}, {}, {}, {}\n", choices[0], choices[1], choices[2], choices[3]);
let expr = io::stdin().read_line().ok().expect("Failed to read line!");
if check_input(expr, &choices) { break; }
print!("Try again? (y/n): ");
let choice = io::stdin().read_line().ok().expect("Failed to read line!");
if choice.as_slice().trim() != "y" { break; }
}
}
fn check_input(expr: String, choices: &Vec<uint>) -> bool {
let mut stack: Vec<uint> = Vec::new();
for token in expr.as_slice().words() {
if is_operator(token) {
let (a, b) = (stack.pop(), stack.pop());
match (a, b) {
(Some(x), Some(y)) => stack.push(evaluate(y, x, token)),
(_, _) => {
println!("Not a valid RPN expression!");
return false ;
}
}
} else {
let v: Option<uint> = from_str(token);
match v {
Some(n) => {
if !is_valid_number(n, choices) {
println!("Cannot use {}", n);
return false;
}
stack.push(n)
},
None => {
println!("Invalid input: {}", token);
return false;
}
}
}
}
let ans = stack.pop();
if stack.len() > 0 {
println!("Not a valid RPN expression!");
return false;
}
match ans {
Some(x) => {
if x == 24 {
println!("Good job!");
return true;
}
println!("Wrong answer. Result: {}", x);
}
None => println!("Error encountered!"),
}
false
}
fn evaluate(a: uint, b: uint, op: &str) -> uint {
match op {
"+" => a + b,
"-" => a - b,
"*" => a * b,
_ => a / b, // has to be /
}
}
fn is_operator(op: &str) -> bool {
match op {
"*" | "-" | "+" | "/" => true,
_ => false
}
}
fn is_valid_number(n: uint, choices: &Vec<uint>) -> bool {
for i in choices.iter() {
if n == *i { return true }
}
false
}
#[test]
fn test_check_input() {
let v1: Vec<uint> = vec![4, 3, 6, 2];
// correct result
let result1 = check_input("4 3 * 6 2 * +".to_string(), &v1);
assert!(result1);
// incorrect result
let result2 = check_input("4 3 + 2 6 + -".to_string(), &v1);
assert!(!result2);
// wrong input
let result3 = check_input("4 5 + 6 2 * -".to_string(), &v1);
assert!(!result3);
// invalid input
let result4 = check_input("4 ) + _ 2 * -".to_string(), &v1);
assert!(!result4);
// invalid RPN expression
let result5 = check_input("4 3 + 6 2 *".to_string(), &v1);
assert!(!result5);
}
@prakhar1989
Copy link
Author

❯ ./build/24_game                      
Make 24 with the following numbers
Your numbers: 9, 1, 1, 4
9 1 + 1 4 + *
Wrong answer. Result: 50
Try again? (y/n): y
Your numbers: 9, 1, 1, 4
9 1 - 4 1 - *
Good job!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment