[TASK] Solved Day 11
This commit is contained in:
55
input/day11.txt
Normal file
55
input/day11.txt
Normal 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
27
input/day11_example.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
|
||||||
193
src/day11.rs
Normal file
193
src/day11.rs
Normal 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
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ use crate::day7::Day7;
|
|||||||
use crate::day8::Day8;
|
use crate::day8::Day8;
|
||||||
use crate::day9::Day9;
|
use crate::day9::Day9;
|
||||||
use crate::day10::Day10;
|
use crate::day10::Day10;
|
||||||
|
use crate::day11::Day11;
|
||||||
use crate::day_solver::DaySolver;
|
use crate::day_solver::DaySolver;
|
||||||
|
|
||||||
mod util;
|
mod util;
|
||||||
@@ -23,8 +24,9 @@ mod day7;
|
|||||||
mod day8;
|
mod day8;
|
||||||
mod day9;
|
mod day9;
|
||||||
mod day10;
|
mod day10;
|
||||||
|
mod day11;
|
||||||
|
|
||||||
const MAX_DAY: u8 = 9;
|
const MAX_DAY: u8 = 11;
|
||||||
const DEFAULT_BENCHMARK_AMOUNT: u32 = 100;
|
const DEFAULT_BENCHMARK_AMOUNT: u32 = 100;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -98,6 +100,7 @@ fn build_day_solver(day: u8) -> Option<Box<dyn DaySolver>> {
|
|||||||
8 => Some(Box::new(Day8::create())),
|
8 => Some(Box::new(Day8::create())),
|
||||||
9 => Some(Box::new(Day9::create())),
|
9 => Some(Box::new(Day9::create())),
|
||||||
10 => Some(Box::new(Day10::create())),
|
10 => Some(Box::new(Day10::create())),
|
||||||
|
11 => Some(Box::new(Day11::create())),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user