[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::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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user