[TASK] Solved Day 11

This commit is contained in:
2022-12-12 08:55:01 +01:00
parent e33875103f
commit 33027001d2
4 changed files with 279 additions and 1 deletions

55
input/day11.txt Normal file
View File

@@ -0,0 +1,55 @@
Monkey 0:
Starting items: 61
Operation: new = old * 11
Test: divisible by 5
If true: throw to monkey 7
If false: throw to monkey 4
Monkey 1:
Starting items: 76, 92, 53, 93, 79, 86, 81
Operation: new = old + 4
Test: divisible by 2
If true: throw to monkey 2
If false: throw to monkey 6
Monkey 2:
Starting items: 91, 99
Operation: new = old * 19
Test: divisible by 13
If true: throw to monkey 5
If false: throw to monkey 0
Monkey 3:
Starting items: 58, 67, 66
Operation: new = old * old
Test: divisible by 7
If true: throw to monkey 6
If false: throw to monkey 1
Monkey 4:
Starting items: 94, 54, 62, 73
Operation: new = old + 1
Test: divisible by 19
If true: throw to monkey 3
If false: throw to monkey 7
Monkey 5:
Starting items: 59, 95, 51, 58, 58
Operation: new = old + 3
Test: divisible by 11
If true: throw to monkey 0
If false: throw to monkey 4
Monkey 6:
Starting items: 87, 69, 92, 56, 91, 93, 88, 73
Operation: new = old + 8
Test: divisible by 3
If true: throw to monkey 5
If false: throw to monkey 2
Monkey 7:
Starting items: 71, 57, 86, 67, 96, 95
Operation: new = old + 7
Test: divisible by 17
If true: throw to monkey 3
If false: throw to monkey 1

27
input/day11_example.txt Normal file
View 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

193
src/day11.rs Normal file
View File

@@ -0,0 +1,193 @@
use crate::day_solver::DaySolver;
use super::util;
pub struct Day11 {
monkeys: Vec<Monkey>
}
impl Day11 {
pub fn create() -> Self {
// let lines = util::read_file("input/day11_example.txt");
let lines = util::read_file("input/day11.txt");
let mut lines_it = lines.iter();
let mut monkeys = Vec::new();
while let Some(line) = lines_it.next() {
if line.starts_with("Monkey") {
// Let's parse the whole monkey
let start_items_line = lines_it.next().unwrap();
assert!(start_items_line.starts_with(" Starting items: "));
let items: Vec<u64> = (&start_items_line[" Starting items: ".len()..])
.split(", ").filter_map(|s| s.parse::<u64>().ok()).collect();
let operation_line = lines_it.next().unwrap();
assert!(operation_line.starts_with(" Operation: new = "));
let mut operation_split = (&operation_line[" Operation: new = ".len()..]).split_whitespace();
let operation = Operation {
arg1: OperationVar::parse(operation_split.next().unwrap()),
op: operation_split.next().unwrap().chars().next().unwrap(),
arg2: OperationVar::parse(operation_split.next().unwrap())
};
let test_line = lines_it.next().unwrap();
assert!(test_line.starts_with(" Test: divisible by "));
let check_divisor = (&test_line[" Test: divisible by ".len()..]).parse::<u64>().unwrap();
let if_true_line = lines_it.next().unwrap();
assert!(if_true_line.starts_with(" If true: throw to monkey "));
let if_true_throw_to_monkey = (&if_true_line[" If true: throw to monkey ".len()..]).parse::<usize>().unwrap();
let if_false_line = lines_it.next().unwrap();
assert!(if_false_line.starts_with(" If false: throw to monkey "));
let if_false_throw_to_monkey = (&if_false_line[" If false: throw to monkey ".len()..]).parse::<usize>().unwrap();
monkeys.push(Monkey {
items,
operation,
test: MonkeyTest { check_divisor, if_true_throw_to_monkey, if_false_throw_to_monkey }
})
}
}
// Put the input into the day struct
return Day11 {
monkeys
}
}
}
impl DaySolver for Day11 {
fn solve_part1(&mut self) -> String {
// println!("{:?}", self.monkeys);
let mut monkey_items: Vec<Vec<u64>> = self.monkeys.iter()
.map(|m| m.items.to_owned()).collect();
let mut monkey_inspection_counts: Vec<usize> = vec![0; self.monkeys.len()];
for _round in 0..20 {
let mut monkey_id = 0;
for monkey in &self.monkeys {
let cur_monkey_items = monkey_items[monkey_id].to_owned();
monkey_inspection_counts[monkey_id] += cur_monkey_items.len();
monkey_items[monkey_id].clear();
for item in &cur_monkey_items {
let item_worry_level = (monkey.operation.execute(item)) / 3;
if item_worry_level % monkey.test.check_divisor == 0 {
monkey_items[monkey.test.if_true_throw_to_monkey].push(item_worry_level);
} else {
monkey_items[monkey.test.if_false_throw_to_monkey].push(item_worry_level);
}
}
monkey_id += 1;
}
// println!("After round {}, monkey items: ", _round);
// for (i, monkey_items) in monkey_items.iter().enumerate() {
// println!("Monkey {}: {:?}", i, monkey_items);
// }
}
// println!("{:?}", monkey_inspection_counts);
monkey_inspection_counts.sort_by_cached_key(|k| usize::MAX - k);
return (monkey_inspection_counts[0] * monkey_inspection_counts[1]).to_string();
}
fn solve_part2(&mut self) -> String {
let mut monkey_items: Vec<Vec<u64>> = self.monkeys.iter()
.map(|m| m.items.to_owned()).collect();
let mut monkey_inspection_counts: Vec<usize> = vec![0; self.monkeys.len()];
let normalizer = self.monkeys.iter().map(|m| m.test.check_divisor)
.reduce(|a, b| a * b).unwrap();
for _round in 0..10000 {
let mut monkey_id = 0;
for monkey in &self.monkeys {
let cur_monkey_items = monkey_items[monkey_id].to_owned();
monkey_inspection_counts[monkey_id] += cur_monkey_items.len();
monkey_items[monkey_id].clear();
for item in &cur_monkey_items {
let item_worry_level = monkey.operation.execute(item) % normalizer;
if item_worry_level % monkey.test.check_divisor == 0 {
monkey_items[monkey.test.if_true_throw_to_monkey].push(item_worry_level);
} else {
monkey_items[monkey.test.if_false_throw_to_monkey].push(item_worry_level);
}
}
monkey_id += 1;
}
}
monkey_inspection_counts.sort_by_cached_key(|k| usize::MAX - k);
return (monkey_inspection_counts[0] as u64 * monkey_inspection_counts[1] as u64).to_string();
}
}
#[derive(Debug, Clone)]
struct Monkey {
items: Vec<u64>,
operation: Operation,
test: MonkeyTest
}
#[derive(Debug, Clone)]
struct Operation {
op: char,
arg1: OperationVar,
arg2: OperationVar
}
#[derive(Debug, Clone)]
enum OperationVar {
Old,
Num(u64)
}
impl OperationVar {
fn concrete<'a>(&'a self, old: &'a u64) -> &'a u64 {
match self {
OperationVar::Old => old,
OperationVar::Num(x) => x
}
}
fn parse(str: &str) -> Self {
if str == "old" {
OperationVar::Old
} else {
OperationVar::Num(str.parse().unwrap())
}
}
}
impl Operation {
fn execute(&self, old: &u64) -> u64 {
let arg1 = self.arg1.concrete(old);
let arg2 = self.arg2.concrete(old);
match self.op {
'*' => arg1 * arg2,
'+' => arg1 + arg2,
_ => panic!("Unsupported operation: {}", self.op)
}
}
}
#[derive(Debug, Clone)]
struct MonkeyTest {
check_divisor: u64,
if_true_throw_to_monkey: usize,
if_false_throw_to_monkey: usize
}

View File

@@ -9,6 +9,7 @@ use crate::day7::Day7;
use crate::day8::Day8;
use crate::day9::Day9;
use crate::day10::Day10;
use crate::day11::Day11;
use crate::day_solver::DaySolver;
mod util;
@@ -23,8 +24,9 @@ mod day7;
mod day8;
mod day9;
mod day10;
mod day11;
const MAX_DAY: u8 = 9;
const MAX_DAY: u8 = 11;
const DEFAULT_BENCHMARK_AMOUNT: u32 = 100;
fn main() {
@@ -98,6 +100,7 @@ fn build_day_solver(day: u8) -> Option<Box<dyn DaySolver>> {
8 => Some(Box::new(Day8::create())),
9 => Some(Box::new(Day9::create())),
10 => Some(Box::new(Day10::create())),
11 => Some(Box::new(Day11::create())),
_ => None
}
}