You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
2.5 KiB

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<f64> = 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<bool, ()> {
let tiles = positions
.iter()
.map(|&pos| board.get(pos.x, pos.y))
.collect::<Option<Vec<Tile>>>()
.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));
}
}