Day 11 part 1

This commit is contained in:
Wesley Moore 2022-12-11 22:05:35 +10:00
parent e507bba147
commit 1a1dda4306
No known key found for this signature in database
4 changed files with 247 additions and 0 deletions

18
2022/Cargo.lock generated
View file

@ -5,3 +5,21 @@ version = 3
[[package]] [[package]]
name = "advent-of-code" name = "advent-of-code"
version = "0.1.0" version = "0.1.0"
dependencies = [
"regex",
]
[[package]]
name = "regex"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"

View file

@ -6,3 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
regex = { version = "1.7.0", default-features = false, features = ["std", "unicode-perl"] }

55
2022/input/day_11.txt Normal file
View file

@ -0,0 +1,55 @@
Monkey 0:
Starting items: 57, 58
Operation: new = old * 19
Test: divisible by 7
If true: throw to monkey 2
If false: throw to monkey 3
Monkey 1:
Starting items: 66, 52, 59, 79, 94, 73
Operation: new = old + 1
Test: divisible by 19
If true: throw to monkey 4
If false: throw to monkey 6
Monkey 2:
Starting items: 80
Operation: new = old + 6
Test: divisible by 5
If true: throw to monkey 7
If false: throw to monkey 5
Monkey 3:
Starting items: 82, 81, 68, 66, 71, 83, 75, 97
Operation: new = old + 5
Test: divisible by 11
If true: throw to monkey 5
If false: throw to monkey 2
Monkey 4:
Starting items: 55, 52, 67, 70, 69, 94, 90
Operation: new = old * old
Test: divisible by 17
If true: throw to monkey 0
If false: throw to monkey 3
Monkey 5:
Starting items: 69, 85, 89, 91
Operation: new = old + 7
Test: divisible by 13
If true: throw to monkey 1
If false: throw to monkey 7
Monkey 6:
Starting items: 75, 53, 73, 52, 75
Operation: new = old * 7
Test: divisible by 2
If true: throw to monkey 0
If false: throw to monkey 4
Monkey 7:
Starting items: 94, 60, 79
Operation: new = old + 2
Test: divisible by 3
If true: throw to monkey 1
If false: throw to monkey 6

173
2022/src/bin/day11.rs Normal file
View file

@ -0,0 +1,173 @@
use regex::Regex;
use std::error::Error;
#[derive(Debug)]
struct Monkey {
items: Vec<isize>,
op: Operation,
test: Test,
items_inspected: usize,
}
#[derive(Debug)]
struct Operation {
operator: char,
operand1: Operand,
operand2: Operand,
}
#[derive(Debug)]
struct Test {
divisible_by: isize,
if_true: usize,
if_false: usize,
}
#[derive(Debug)]
enum Operand {
Old,
Const(isize),
}
struct TurnResult {
if_true: (usize, Vec<isize>),
if_false: (usize, Vec<isize>),
}
fn main() -> Result<(), Box<dyn Error>> {
let input = std::fs::read_to_string("input/day_11.txt")?;
let re = Regex::new(
r"^Monkey \d:
Starting items: (?P<items>.+)
Operation: new = (?P<opa>\w+) (?P<op>.) (?P<opb>\w+)
Test: divisible by (?P<div>\d+)
If true: throw to monkey (?P<if_true>\d+)
If false: throw to monkey (?P<if_false>\d+)$",
)?;
part1(&input, &re)?;
part2(&input)?;
Ok(())
}
fn part1(input: &str, re: &Regex) -> Result<(), Box<dyn Error>> {
let mut monkeys = input
.split("\n\n")
.map(|s| parse_monkey(s, re))
.collect::<Result<Vec<_>, _>>()?;
for _round in 0..20 {
for i in 0..monkeys.len() {
take_turn(i, &mut monkeys)
}
}
monkeys.sort_by(|a, b| a.items_inspected.cmp(&b.items_inspected));
let monkey_business =
monkeys[monkeys.len() - 2].items_inspected * monkeys[monkeys.len() - 1].items_inspected;
println!("Monkey business: {}", monkey_business);
Ok(())
}
fn part2(input: &str) -> Result<(), Box<dyn Error>> {
Ok(())
}
fn parse_monkey(input: &str, re: &Regex) -> Result<Monkey, Box<dyn Error>> {
let caps = re
.captures(input.trim())
.ok_or_else(|| format!("text did not match regex: {}", input))?;
let items = caps
.name("items")
.unwrap()
.as_str()
.split(", ")
.map(|item| item.parse())
.collect::<Result<Vec<isize>, _>>()?;
let opa = parse_operand(caps.name("opa").unwrap().as_str())?;
let opb = parse_operand(caps.name("opb").unwrap().as_str())?;
let op = caps.name("op").unwrap().as_str().chars().next().unwrap();
let div = caps.name("div").unwrap().as_str().parse()?;
let if_true = caps.name("if_true").unwrap().as_str().parse()?;
let if_false = caps.name("if_false").unwrap().as_str().parse()?;
Ok(Monkey {
items,
op: Operation {
operator: op,
operand1: opa,
operand2: opb,
},
test: Test {
divisible_by: div,
if_true,
if_false,
},
items_inspected: 0,
})
}
fn parse_operand(input: &str) -> Result<Operand, Box<dyn Error>> {
match input {
"old" => Ok(Operand::Old),
otherwise => {
let val = otherwise.parse()?;
Ok(Operand::Const(val))
}
}
}
fn take_turn(i: usize, monkeys: &mut [Monkey]) {
let mut res = monkeys[i].take_turn();
monkeys[res.if_true.0].items.append(&mut res.if_true.1);
monkeys[res.if_false.0].items.append(&mut res.if_false.1);
}
impl Monkey {
fn take_turn(&mut self) -> TurnResult {
let mut if_true = Vec::new();
let mut if_false = Vec::new();
for item in self.items.iter().copied() {
let new = self.op.eval(item) / 3;
if self.test.test(new) {
if_true.push(new);
} else {
if_false.push(new);
}
}
self.items_inspected += self.items.len();
self.items.clear();
TurnResult {
if_true: (self.test.if_true, if_true),
if_false: (self.test.if_false, if_false),
}
}
}
impl Operation {
fn eval(&self, old: isize) -> isize {
match self.operator {
'+' => self.operand1.val(old) + self.operand2.val(old),
'*' => self.operand1.val(old) * self.operand2.val(old),
_ => unreachable!("unknown op"),
}
}
}
impl Operand {
fn val(&self, old: isize) -> isize {
match self {
Operand::Old => old,
Operand::Const(v) => *v,
}
}
}
impl Test {
fn test(&self, item: isize) -> bool {
item % self.divisible_by == 0
}
}