use std::env::args; use std::fs::File; use std::io::BufRead; use std::io::BufReader; #[derive(PartialEq, Debug, Copy, Clone)] enum Token { Add, Mul, Div, Mod, Eql, Int(i64), Var(usize), Input(u8), } fn print_formular(formular: &mut std::slice::Iter<'_, Token>) { match formular.next() { Some(Token::Add) => { print!("("); print_formular(formular); print!(" + "); print_formular(formular); print!(")"); }, Some(Token::Mul) => { print!("("); print_formular(formular); print!(" * "); print_formular(formular); print!(")"); }, Some(Token::Div) => { print!("("); print_formular(formular); print!(" / "); print_formular(formular); print!(")"); }, Some(Token::Mod) => { print!("("); print_formular(formular); print!(" % "); print_formular(formular); print!(")"); }, Some(Token::Eql) => { print!("("); print_formular(formular); print!(" == "); print_formular(formular); print!(")"); }, Some(Token::Int(i)) => { print!("{}", i); }, Some(Token::Input(i)) => { print!("in{}", i); }, _ => unreachable!(), } } fn get_data() -> Vec<(Token, Token, Token)> { let path = args().nth(1).unwrap(); let file = File::open(path).unwrap(); let mut lines = vec![]; let mut input = 0; for line in BufReader::new(file).lines() { let l = line.unwrap(); match l.split(" ").collect::>()[..] { ["inp", a] => { lines.push(( Token::Input(input), Token::Var(match a { "z" => 0, "y" => 1, "x" => 2, "w" => 3, _ => unreachable!(), }), Token::Int(0), )); input += 1; }, [op, a, b] => { lines.push(( match op { "add" => Token::Add, "mul" => Token::Mul, "div" => Token::Div, "mod" => Token::Mod, "eql" => Token::Eql, _ => unreachable!(), }, Token::Var(match a { "z" => 0, "y" => 1, "x" => 2, "w" => 3, _ => unreachable!(), }), match b.parse::() { Ok(bi) => Token::Int(bi), Err(_) => Token::Var(match b { "z" => 0, "y" => 1, "x" => 2, "w" => 3, _ => unreachable!(), }), }, )); }, _ => unreachable!(), } } return lines; } fn foo(inputs: &[Option; 14], lines: &Vec<(Token, Token, Token)>) -> bool { let mut mins = [0; 4]; let mut maxs = [0; 4]; for line in lines.iter() { match line { (Token::Input(input), Token::Var(c), _) => { match inputs[*input as usize] { Some(value) => { mins[*c] = value; maxs[*c] = value; }, None => { mins[*c] = 1; maxs[*c] = 9; }, } }, (op, Token::Var(c), b) => { let left_min = mins[*c]; let left_max = maxs[*c]; let (right_min, right_max): (i64, i64) = match b { Token::Int(bi) => (*bi, *bi), Token::Var(bc) => (mins[*bc], maxs[*bc]), _ => unreachable!(), }; match op { Token::Add => { mins[*c] = left_min + right_min; maxs[*c] = left_max + right_max; }, Token::Mul => { mins[*c] = *vec![left_min * right_min, left_max * right_min, left_min * right_max, left_min * right_min].iter().min().unwrap(); maxs[*c] = *vec![left_min * right_min, left_max * right_min, left_min * right_max, left_min * right_min].iter().max().unwrap(); }, Token::Div => { mins[*c] = *vec![left_min / right_min, left_max / right_min, left_min / right_max, left_min / right_min].iter().min().unwrap(); maxs[*c] = *vec![left_min / right_min, left_max / right_min, left_min / right_max, left_min / right_min].iter().max().unwrap(); }, Token::Mod => { if left_min == left_max && right_min == right_max { let v = left_min % right_min; mins[*c] = v; maxs[*c] = v; } else { mins[*c] = 0; maxs[*c] = right_max - 1; } }, Token::Eql => { if left_min == left_max && right_min == right_max { let v = if left_min == right_min {1} else {0}; mins[*c] = v; maxs[*c] = v; } else { mins[*c] = 0; maxs[*c] = 1; } }, _ => unreachable!(), } }, _ => unreachable!(), } } return mins[0] <= 0 && maxs[0] >= 0; } fn bar(i: usize, mut solution: &mut [Option; 14], lines: &Vec<(Token, Token, Token)>) -> bool { if i == 5 { println!("{:?}", solution); } for value in (1..=9).rev() { solution[i] = Some(value); if foo(solution, lines) { if i == 13 { return true; } if bar(i + 1, solution, lines) { return true; } } } solution[i] = None; return false; } fn main() { let lines = get_data(); let mut solution = [None; 14]; bar(0, &mut solution, &lines); for i in solution.iter() { print!("{}", i.unwrap()); } println!(""); }