Add solution for 2022 day 11 part 1
This commit is contained in:
parent
c173b62d37
commit
273a54b4ca
7
2022/Cargo.lock
generated
7
2022/Cargo.lock
generated
@ -48,6 +48,13 @@ version = "0.1.0"
|
|||||||
name = "aoc-2022-10"
|
name = "aoc-2022-10"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aoc-2022-11"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"itertools",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.8.0"
|
version = "1.8.0"
|
||||||
|
@ -10,6 +10,7 @@ members = [
|
|||||||
"./day-08",
|
"./day-08",
|
||||||
"./day-09",
|
"./day-09",
|
||||||
"./day-10",
|
"./day-10",
|
||||||
|
"./day-11",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
| [08] | ✓ | ✓ | [Rust] |
|
| [08] | ✓ | ✓ | [Rust] |
|
||||||
| [09] | ✓ | ✓ | [Rust] |
|
| [09] | ✓ | ✓ | [Rust] |
|
||||||
| [10] | ✓ | ✓ | [Rust] |
|
| [10] | ✓ | ✓ | [Rust] |
|
||||||
| [11] | | | |
|
| [11] | ✓ | | [Rust] |
|
||||||
| [12] | | | |
|
| [12] | | | |
|
||||||
| [13] | | | |
|
| [13] | | | |
|
||||||
| [14] | | | |
|
| [14] | | | |
|
||||||
|
13
2022/day-11/Cargo.toml
Normal file
13
2022/day-11/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "aoc-2022-11"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
test = false
|
||||||
|
doctest = false
|
||||||
|
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
itertools = "0.10.5"
|
5
2022/day-11/Justfile
Normal file
5
2022/day-11/Justfile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
@part PART INPUT_FILE="inputs/puzzle.txt":
|
||||||
|
cargo --quiet run --bin part_{{PART}} -- {{INPUT_FILE}}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
cargo clean
|
55
2022/day-11/inputs/puzzle.txt
Normal file
55
2022/day-11/inputs/puzzle.txt
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
Monkey 0:
|
||||||
|
Starting items: 99, 63, 76, 93, 54, 73
|
||||||
|
Operation: new = old * 11
|
||||||
|
Test: divisible by 2
|
||||||
|
If true: throw to monkey 7
|
||||||
|
If false: throw to monkey 1
|
||||||
|
|
||||||
|
Monkey 1:
|
||||||
|
Starting items: 91, 60, 97, 54
|
||||||
|
Operation: new = old + 1
|
||||||
|
Test: divisible by 17
|
||||||
|
If true: throw to monkey 3
|
||||||
|
If false: throw to monkey 2
|
||||||
|
|
||||||
|
Monkey 2:
|
||||||
|
Starting items: 65
|
||||||
|
Operation: new = old + 7
|
||||||
|
Test: divisible by 7
|
||||||
|
If true: throw to monkey 6
|
||||||
|
If false: throw to monkey 5
|
||||||
|
|
||||||
|
Monkey 3:
|
||||||
|
Starting items: 84, 55
|
||||||
|
Operation: new = old + 3
|
||||||
|
Test: divisible by 11
|
||||||
|
If true: throw to monkey 2
|
||||||
|
If false: throw to monkey 6
|
||||||
|
|
||||||
|
Monkey 4:
|
||||||
|
Starting items: 86, 63, 79, 54, 83
|
||||||
|
Operation: new = old * old
|
||||||
|
Test: divisible by 19
|
||||||
|
If true: throw to monkey 7
|
||||||
|
If false: throw to monkey 0
|
||||||
|
|
||||||
|
Monkey 5:
|
||||||
|
Starting items: 96, 67, 56, 95, 64, 69, 96
|
||||||
|
Operation: new = old + 4
|
||||||
|
Test: divisible by 5
|
||||||
|
If true: throw to monkey 4
|
||||||
|
If false: throw to monkey 0
|
||||||
|
|
||||||
|
Monkey 6:
|
||||||
|
Starting items: 66, 94, 70, 93, 72, 67, 88, 51
|
||||||
|
Operation: new = old * 5
|
||||||
|
Test: divisible by 13
|
||||||
|
If true: throw to monkey 4
|
||||||
|
If false: throw to monkey 5
|
||||||
|
|
||||||
|
Monkey 7:
|
||||||
|
Starting items: 59, 59, 74
|
||||||
|
Operation: new = old + 8
|
||||||
|
Test: divisible by 3
|
||||||
|
If true: throw to monkey 1
|
||||||
|
If false: throw to monkey 3
|
27
2022/day-11/inputs/test.txt
Normal file
27
2022/day-11/inputs/test.txt
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Monkey 0:
|
||||||
|
Starting items: 79, 98
|
||||||
|
Operation: new = old * 19
|
||||||
|
Test: divisible by 23
|
||||||
|
If true: throw to monkey 2
|
||||||
|
If false: throw to monkey 3
|
||||||
|
|
||||||
|
Monkey 1:
|
||||||
|
Starting items: 54, 65, 75, 74
|
||||||
|
Operation: new = old + 6
|
||||||
|
Test: divisible by 19
|
||||||
|
If true: throw to monkey 2
|
||||||
|
If false: throw to monkey 0
|
||||||
|
|
||||||
|
Monkey 2:
|
||||||
|
Starting items: 79, 60, 97
|
||||||
|
Operation: new = old * old
|
||||||
|
Test: divisible by 13
|
||||||
|
If true: throw to monkey 1
|
||||||
|
If false: throw to monkey 3
|
||||||
|
|
||||||
|
Monkey 3:
|
||||||
|
Starting items: 74
|
||||||
|
Operation: new = old + 3
|
||||||
|
Test: divisible by 17
|
||||||
|
If true: throw to monkey 0
|
||||||
|
If false: throw to monkey 1
|
87
2022/day-11/src/bin/part_one.rs
Normal file
87
2022/day-11/src/bin/part_one.rs
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
use std::{
|
||||||
|
collections::{BTreeMap, HashMap},
|
||||||
|
env, io,
|
||||||
|
};
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
use aoc_2022_11::parse_input;
|
||||||
|
|
||||||
|
fn main() -> io::Result<()> {
|
||||||
|
let infile_path = env::args().nth(1).expect("input file");
|
||||||
|
|
||||||
|
let result = solve(&infile_path)?;
|
||||||
|
|
||||||
|
println!("{result}");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve(path: &str) -> io::Result<u64> {
|
||||||
|
let notes = parse_input(path)?;
|
||||||
|
|
||||||
|
let mut activity_counter = HashMap::<usize, u64>::new();
|
||||||
|
let mut state = notes
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, v)| (i, v.items.clone()))
|
||||||
|
.collect::<BTreeMap<_, _>>();
|
||||||
|
|
||||||
|
for _ in 0..20 {
|
||||||
|
for monkey_id in 0..state.len() {
|
||||||
|
let items = {
|
||||||
|
let state = state.get_mut(&monkey_id).unwrap();
|
||||||
|
state.drain(..).collect::<Vec<_>>()
|
||||||
|
};
|
||||||
|
|
||||||
|
for item in items {
|
||||||
|
activity_counter
|
||||||
|
.entry(monkey_id)
|
||||||
|
.and_modify(|v| *v += 1)
|
||||||
|
.or_insert(1);
|
||||||
|
|
||||||
|
let note = ¬es[monkey_id];
|
||||||
|
|
||||||
|
let new_value = note.operation.apply(item) / 3;
|
||||||
|
|
||||||
|
let next_monkey = if new_value % note.test_mod == 0 {
|
||||||
|
note.next_monkey_when_true
|
||||||
|
} else {
|
||||||
|
note.next_monkey_when_false
|
||||||
|
};
|
||||||
|
|
||||||
|
state
|
||||||
|
.entry(next_monkey)
|
||||||
|
.and_modify(|f| f.push(new_value))
|
||||||
|
.or_insert_with(|| vec![new_value]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let most_active_product = activity_counter
|
||||||
|
.values()
|
||||||
|
.sorted_by(|a, b| b.cmp(a))
|
||||||
|
.take(2)
|
||||||
|
.copied()
|
||||||
|
.reduce(|acc, val| acc * val)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Ok(most_active_product)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample() {
|
||||||
|
let result = solve("inputs/test.txt").unwrap();
|
||||||
|
assert_eq!(10_605, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn puzzle() {
|
||||||
|
let result = solve("inputs/puzzle.txt").unwrap();
|
||||||
|
assert_eq!(316_888, result);
|
||||||
|
}
|
||||||
|
}
|
136
2022/day-11/src/lib.rs
Normal file
136
2022/day-11/src/lib.rs
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
use std::{
|
||||||
|
fs::File,
|
||||||
|
io::{self, Read},
|
||||||
|
path::Path,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub type WorryLevel = u64;
|
||||||
|
pub type MonkeyId = usize;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Param {
|
||||||
|
Old,
|
||||||
|
Val(WorryLevel),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Operation {
|
||||||
|
Mul(Param, Param),
|
||||||
|
Add(Param, Param),
|
||||||
|
Noop,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Operation {
|
||||||
|
pub fn apply(&self, old: WorryLevel) -> WorryLevel {
|
||||||
|
match self {
|
||||||
|
Self::Mul(Param::Old, Param::Val(val)) => old * val,
|
||||||
|
Self::Mul(Param::Old, Param::Old) => old * old,
|
||||||
|
Self::Add(Param::Old, Param::Val(val)) => old + val,
|
||||||
|
Self::Add(Param::Old, Param::Old) => old + old,
|
||||||
|
_ => panic!("unsupported operation"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Note {
|
||||||
|
pub items: Vec<WorryLevel>,
|
||||||
|
pub operation: Operation,
|
||||||
|
pub test_mod: WorryLevel,
|
||||||
|
pub next_monkey_when_true: MonkeyId,
|
||||||
|
pub next_monkey_when_false: MonkeyId,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_input<P>(path: P) -> io::Result<Vec<Note>>
|
||||||
|
where
|
||||||
|
P: AsRef<Path>,
|
||||||
|
{
|
||||||
|
let mut file = File::open(path)?;
|
||||||
|
let mut input = String::new();
|
||||||
|
file.read_to_string(&mut input)?;
|
||||||
|
|
||||||
|
let notes = input.split("\n\n").map(|part| parse_note(part)).collect();
|
||||||
|
|
||||||
|
Ok(notes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_note(input: &str) -> Note {
|
||||||
|
let mut items = vec![];
|
||||||
|
let mut operation = Operation::Noop;
|
||||||
|
let mut test_mod = 0;
|
||||||
|
let mut next_monkey_when_true = 0;
|
||||||
|
let mut next_monkey_when_false = 0;
|
||||||
|
|
||||||
|
for line in input.lines() {
|
||||||
|
let line = line.trim_start();
|
||||||
|
let (val, rem) = line.split_once(':').unwrap();
|
||||||
|
|
||||||
|
match val {
|
||||||
|
"Starting items" => {
|
||||||
|
items = parse_starting_items(rem);
|
||||||
|
}
|
||||||
|
"Operation" => {
|
||||||
|
operation = parse_operation(rem);
|
||||||
|
}
|
||||||
|
"Test" => {
|
||||||
|
test_mod = parse_test(rem);
|
||||||
|
}
|
||||||
|
"If true" => {
|
||||||
|
next_monkey_when_true = parse_next_monkey(rem);
|
||||||
|
}
|
||||||
|
"If false" => {
|
||||||
|
next_monkey_when_false = parse_next_monkey(rem);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Note {
|
||||||
|
items,
|
||||||
|
operation,
|
||||||
|
test_mod,
|
||||||
|
next_monkey_when_true,
|
||||||
|
next_monkey_when_false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_starting_items(input: &str) -> Vec<WorryLevel> {
|
||||||
|
input
|
||||||
|
.split(',')
|
||||||
|
.map(|val| val.trim_start().parse().unwrap())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_operation(input: &str) -> Operation {
|
||||||
|
let input = input.strip_prefix(" new = old ").unwrap();
|
||||||
|
let op_and_val = input.split_whitespace().collect::<Vec<&str>>();
|
||||||
|
match *op_and_val {
|
||||||
|
["*", "old"] => Operation::Mul(Param::Old, Param::Old),
|
||||||
|
["*", val] => {
|
||||||
|
let val = val.parse().unwrap();
|
||||||
|
Operation::Mul(Param::Old, Param::Val(val))
|
||||||
|
}
|
||||||
|
["+", "old"] => Operation::Add(Param::Old, Param::Old),
|
||||||
|
["+", val] => {
|
||||||
|
let val = val.parse().unwrap();
|
||||||
|
Operation::Add(Param::Old, Param::Val(val))
|
||||||
|
}
|
||||||
|
_ => panic!("Unsupported operation"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_test(input: &str) -> WorryLevel {
|
||||||
|
input
|
||||||
|
.strip_prefix(" divisible by ")
|
||||||
|
.unwrap()
|
||||||
|
.parse()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_next_monkey(input: &str) -> MonkeyId {
|
||||||
|
input
|
||||||
|
.strip_prefix(" throw to monkey ")
|
||||||
|
.unwrap()
|
||||||
|
.parse()
|
||||||
|
.unwrap()
|
||||||
|
}
|
@ -9,4 +9,4 @@
|
|||||||
- [2019](2019/README.md) (0% completed)
|
- [2019](2019/README.md) (0% completed)
|
||||||
- [2020](2020/README.md) (20% completed)
|
- [2020](2020/README.md) (20% completed)
|
||||||
- [2021](2021/README.md) (68% completed)
|
- [2021](2021/README.md) (68% completed)
|
||||||
- [2022](2022/README.md) (40% completed)
|
- [2022](2022/README.md) (42% completed)
|
||||||
|
Loading…
Reference in New Issue
Block a user