Day 21, part 2
This commit is contained in:
parent
ec5b46d793
commit
47cb2fefa5
@ -3,5 +3,5 @@ use aoc22::{day21, util};
|
|||||||
pub fn main() {
|
pub fn main() {
|
||||||
let monkeys = day21::parse_monkeys(&util::parse_input());
|
let monkeys = day21::parse_monkeys(&util::parse_input());
|
||||||
|
|
||||||
println!("root yells: {}", day21::yell(monkeys.root()));
|
println!("root yells: {}", day21::yell(monkeys.root(), false));
|
||||||
}
|
}
|
||||||
|
9
src/bin/d21p2.rs
Normal file
9
src/bin/d21p2.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
use aoc22::{day21, util};
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let monkeys = day21::parse_monkeys(&util::parse_input());
|
||||||
|
|
||||||
|
let human = day21::find(&monkeys, "humn").unwrap();
|
||||||
|
|
||||||
|
println!("Human should yell: {}", day21::find_solution(human));
|
||||||
|
}
|
98
src/day21.rs
98
src/day21.rs
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
|||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use trees::{tr, Node, Tree};
|
use trees::{tr, Node, Tree};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub enum Operation {
|
pub enum Operation {
|
||||||
Add,
|
Add,
|
||||||
Sub,
|
Sub,
|
||||||
@ -23,12 +23,18 @@ impl Operation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Monkey {
|
pub enum MonkeyKind {
|
||||||
Number(isize),
|
Number(isize),
|
||||||
Calculate(String, String, Operation),
|
Calculate(String, String, Operation),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct Monkey {
|
||||||
|
pub name: String,
|
||||||
|
pub kind: MonkeyKind,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_monkeys(input: &String) -> Tree<Monkey> {
|
pub fn parse_monkeys(input: &String) -> Tree<Monkey> {
|
||||||
let mut monkeys = HashMap::new();
|
let mut monkeys = HashMap::new();
|
||||||
|
|
||||||
@ -36,16 +42,22 @@ pub fn parse_monkeys(input: &String) -> Tree<Monkey> {
|
|||||||
for line in input.lines() {
|
for line in input.lines() {
|
||||||
let captures = re.captures(line).unwrap();
|
let captures = re.captures(line).unwrap();
|
||||||
let name = captures.get(1).unwrap().as_str();
|
let name = captures.get(1).unwrap().as_str();
|
||||||
let monkey = if let Some(num) = captures.get(2) {
|
let kind = if let Some(num) = captures.get(2) {
|
||||||
Monkey::Number(num.as_str().parse().unwrap())
|
MonkeyKind::Number(num.as_str().parse().unwrap())
|
||||||
} else {
|
} else {
|
||||||
Monkey::Calculate(
|
MonkeyKind::Calculate(
|
||||||
captures.get(3).unwrap().as_str().to_owned(),
|
captures.get(3).unwrap().as_str().to_owned(),
|
||||||
captures.get(5).unwrap().as_str().to_owned(),
|
captures.get(5).unwrap().as_str().to_owned(),
|
||||||
Operation::from(captures.get(4).unwrap().as_str()),
|
Operation::from(captures.get(4).unwrap().as_str()),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
monkeys.insert(name.to_owned(), monkey);
|
monkeys.insert(
|
||||||
|
name.to_owned(),
|
||||||
|
Monkey {
|
||||||
|
name: name.to_owned(),
|
||||||
|
kind,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let tree = to_tree(&monkeys, "root");
|
let tree = to_tree(&monkeys, "root");
|
||||||
@ -57,7 +69,7 @@ fn to_tree(monkeys: &HashMap<String, Monkey>, monkey: &str) -> Tree<Monkey> {
|
|||||||
let monkey = &monkeys[monkey];
|
let monkey = &monkeys[monkey];
|
||||||
let mut tree = tr(monkey.clone());
|
let mut tree = tr(monkey.clone());
|
||||||
|
|
||||||
if let Monkey::Calculate(a, b, _) = monkey {
|
if let MonkeyKind::Calculate(a, b, _) = &monkey.kind {
|
||||||
let forest = -to_tree(monkeys, a) - to_tree(monkeys, b);
|
let forest = -to_tree(monkeys, a) - to_tree(monkeys, b);
|
||||||
tree.append(forest);
|
tree.append(forest);
|
||||||
}
|
}
|
||||||
@ -65,19 +77,73 @@ fn to_tree(monkeys: &HashMap<String, Monkey>, monkey: &str) -> Tree<Monkey> {
|
|||||||
tree
|
tree
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn yell(monkey: &Node<Monkey>) -> isize {
|
pub fn yell(monkey: &Node<Monkey>, no_human: bool) -> isize {
|
||||||
match monkey.data() {
|
if no_human {
|
||||||
Monkey::Number(n) => *n,
|
assert!(monkey.data().name != "humn");
|
||||||
Monkey::Calculate(_, _, op) => {
|
}
|
||||||
|
|
||||||
|
match &monkey.data().kind {
|
||||||
|
MonkeyKind::Number(n) => *n,
|
||||||
|
MonkeyKind::Calculate(_, _, op) => {
|
||||||
let mut children = monkey.iter();
|
let mut children = monkey.iter();
|
||||||
let a = children.next().unwrap();
|
let a = children.next().unwrap();
|
||||||
let b = children.next().unwrap();
|
let b = children.next().unwrap();
|
||||||
match op {
|
match op {
|
||||||
Operation::Add => yell(a) + yell(b),
|
Operation::Add => yell(a, no_human) + yell(b, no_human),
|
||||||
Operation::Sub => yell(a) - yell(b),
|
Operation::Sub => yell(a, no_human) - yell(b, no_human),
|
||||||
Operation::Mul => yell(a) * yell(b),
|
Operation::Mul => yell(a, no_human) * yell(b, no_human),
|
||||||
Operation::Div => yell(a) / yell(b),
|
Operation::Div => yell(a, no_human) / yell(b, no_human),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn find_solution(target: &Node<Monkey>) -> isize {
|
||||||
|
let parent = target.parent().unwrap();
|
||||||
|
let other_pos = parent.iter().position(|n| n != target).unwrap();
|
||||||
|
assert!(other_pos < 2);
|
||||||
|
let sibling = parent.iter().nth(other_pos).unwrap();
|
||||||
|
let other = yell(sibling, true);
|
||||||
|
|
||||||
|
if parent.parent().is_none() {
|
||||||
|
other
|
||||||
|
} else {
|
||||||
|
let parent_target = find_solution(parent);
|
||||||
|
if let MonkeyKind::Calculate(_, _, op) = parent.data().kind {
|
||||||
|
match op {
|
||||||
|
Operation::Add => parent_target - other,
|
||||||
|
Operation::Sub => {
|
||||||
|
if other_pos == 0 {
|
||||||
|
other - parent_target
|
||||||
|
} else {
|
||||||
|
other + parent_target
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Operation::Mul => parent_target / other,
|
||||||
|
Operation::Div => {
|
||||||
|
if other_pos == 0 {
|
||||||
|
other / parent_target
|
||||||
|
} else {
|
||||||
|
parent_target * other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("Parent does not calculate!?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find<'a>(monkeys: &'a Tree<Monkey>, name: &str) -> Option<&'a Node<Monkey>> {
|
||||||
|
let mut next = vec![monkeys.root()];
|
||||||
|
|
||||||
|
while let Some(n) = next.pop() {
|
||||||
|
let data = n.data();
|
||||||
|
if data.name == name {
|
||||||
|
return Some(n);
|
||||||
|
}
|
||||||
|
next.extend(n.iter());
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user