mirror of
https://github.com/wezm/advent-of-code.git
synced 2024-11-09 09:22:33 +00:00
Day 11 part 1
This commit is contained in:
parent
e507bba147
commit
1a1dda4306
4 changed files with 247 additions and 0 deletions
18
2022/Cargo.lock
generated
18
2022/Cargo.lock
generated
|
@ -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"
|
||||||
|
|
|
@ -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
55
2022/input/day_11.txt
Normal 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
173
2022/src/bin/day11.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue