use std::{collections::HashMap, hash::Hash}; enum Operand { Ind(String), Dir(i64), } impl Operand { fn from(op :&str) -> Self { match op.parse::() { Ok(i) => { Operand::Dir(i) } Err(_) => { Operand::Ind(op.to_owned()) } } } } enum Operation { ADD, SUB, MUL, DIV, } impl Operation { fn from(op :&str) -> Self { match op { "+" => { Operation::ADD } "-" => { Operation::SUB } "*" => { Operation::MUL } "/" => { Operation::DIV } _ => { std::process::exit(1) } } } } struct Monkey { op1 :Operand, op2 :Operand, operation :Operation, } enum MonkeyExcl { Monkey(Monkey), Num(i64), } impl Monkey { fn from(operation :Operation, op1 :Operand, op2 :Operand) -> Self { Monkey { op1: op1, op2: op2, operation: operation } } } fn find_result(goal :String, map :&HashMap) -> i64 { let monk = map.get(&goal).unwrap(); match monk { MonkeyExcl::Num(i) => { *i } MonkeyExcl::Monkey(monk) => { let op1 = { match &monk.op1 { Operand::Dir(i) => { *i } Operand::Ind(s) => { find_result(s.to_string(), map) } } }; let op2 = { match &monk.op2 { Operand::Dir(i) => { *i } Operand::Ind(s) => { find_result(s.to_string(), map) } } }; match monk.operation { Operation::ADD => { op1 + op2 } Operation::SUB => { op1 - op2 } Operation::MUL => { op1 * op2 } Operation::DIV => { op1 / op2 } } } } } pub fn run(inp :Vec) { let map :HashMap = inp.iter().map(|elem| { let repl = elem.replace(":", ""); let tmp = repl.split(' ').collect::>(); if tmp.len() == 2 { (tmp[0].to_owned(), MonkeyExcl::Num(tmp[1].parse::().unwrap())) } else { let monk = Monkey::from(Operation::from(tmp[2]), Operand::from(tmp[1]), Operand::from(tmp[3])); (tmp[0].to_owned(), MonkeyExcl::Monkey(monk)) } }).collect(); let result = find_result("root".to_owned(), &map); println!("a1: {}", result); }