use crate::board::Board; use crate::lexer::lexer; use crate::parser; use crate::parser::{Expression, Expressions}; use crate::position::Position2d; use crate::tile::{Operator, Tile}; pub fn calculate(expr: &Expression) -> f64 { match expr { Expression::Digit(value) => *value as f64, Expression::Parentheses(expr) => calculate(expr), Expression::Binary(operator, left, right) => { let left = calculate(left); let right = calculate(right); match operator { Operator::Add => left + right, Operator::Subtract => left - right, Operator::Multiply => left * right, Operator::Divide => left / right, } } } } pub fn are_valid_expressions(expr: &Expressions) -> bool { let mut res: Option = None; for expr in expr { let value = calculate(expr); if let Some(res) = res { if res != value { return false; } } else { res = Some(value); } } res.is_some() } pub fn is_valid_guess(board: &Board, positions: &[Position2d]) -> Result { let tiles = positions .iter() .map(|&pos| board.get(pos.x, pos.y)) .collect::>>() .ok_or(())?; let tokens = lexer(&tiles)?; let expressions = parser::parse(&tokens)?; Ok(are_valid_expressions(&expressions)) } #[cfg(test)] mod tests { use super::*; #[test] fn test_calculate() { let expr = Expression::Binary( Operator::Add, Box::new(Expression::Digit(1)), Box::new(Expression::Digit(2)), ); assert_eq!(calculate(&expr), 3.0); } #[test] fn test_are_valid_expressions() { let expr = vec![ Expression::Binary( Operator::Add, Box::new(Expression::Digit(3)), Box::new(Expression::Digit(4)), ), Expression::Binary( Operator::Add, Box::new(Expression::Digit(6)), Box::new(Expression::Digit(1)), ), ]; assert!(are_valid_expressions(&expr)); let expr = vec![ Expression::Digit(9), Expression::Binary( Operator::Add, Box::new(Expression::Digit(7)), Box::new(Expression::Digit(1)), ), ]; assert!(!are_valid_expressions(&expr)); } }