Skip to content

Commit

Permalink
day 11
Browse files Browse the repository at this point in the history
  • Loading branch information
carlosflorencio committed Dec 13, 2022
1 parent 2b9ad1d commit 52a8c92
Show file tree
Hide file tree
Showing 3 changed files with 257 additions and 0 deletions.
55 changes: 55 additions & 0 deletions input/2022/day11.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
Monkey 0:
Starting items: 75, 75, 98, 97, 79, 97, 64
Operation: new = old * 13
Test: divisible by 19
If true: throw to monkey 2
If false: throw to monkey 7

Monkey 1:
Starting items: 50, 99, 80, 84, 65, 95
Operation: new = old + 2
Test: divisible by 3
If true: throw to monkey 4
If false: throw to monkey 5

Monkey 2:
Starting items: 96, 74, 68, 96, 56, 71, 75, 53
Operation: new = old + 1
Test: divisible by 11
If true: throw to monkey 7
If false: throw to monkey 3

Monkey 3:
Starting items: 83, 96, 86, 58, 92
Operation: new = old + 8
Test: divisible by 17
If true: throw to monkey 6
If false: throw to monkey 1

Monkey 4:
Starting items: 99
Operation: new = old * old
Test: divisible by 5
If true: throw to monkey 0
If false: throw to monkey 5

Monkey 5:
Starting items: 60, 54, 83
Operation: new = old + 4
Test: divisible by 2
If true: throw to monkey 2
If false: throw to monkey 0

Monkey 6:
Starting items: 77, 67
Operation: new = old * 17
Test: divisible by 13
If true: throw to monkey 4
If false: throw to monkey 1

Monkey 7:
Starting items: 95, 65, 58, 76
Operation: new = old + 5
Test: divisible by 7
If true: throw to monkey 3
If false: throw to monkey 6
201 changes: 201 additions & 0 deletions src/day11.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
#[derive(Clone)]
struct Operation {
str: String,
}

impl Operation {
fn apply(&self, item: u64) -> u64 {
let parts: Vec<&str> = self.str.split(" ").collect();

let mut right: u64 = item;
if parts[2] != "old" {
right = parts[2].parse::<u64>().unwrap();
}

match parts[1] {
"*" => item.wrapping_mul(right),
"+" => item.wrapping_add(right),
_ => panic!("operator not implemented"),
}
}
}

#[derive(Clone)]
struct Test {
divisible: u64,
target_positive: usize,
target_negative: usize,
}

impl Test {
fn result(&self, item: u64) -> usize {
if item % self.divisible == 0 {
self.target_positive
} else {
self.target_negative
}
}
}

#[derive(Clone)]
struct Monkey {
items: Vec<u64>,
operation: Operation,
test: Test,
inspections: usize,
}

impl Monkey {
fn turn(&mut self, transform: impl Fn(u64) -> u64) -> Vec<(usize, u64)> {
let mut give: Vec<(usize, u64)> = Vec::new();

loop {
if self.items.len() == 0 {
break;
}

self.inspections += 1;
let mut c = self.operation.apply(self.items.pop().unwrap());
c = transform(c);

let target = self.test.result(c);

give.push((target, c));

if self.items.len() == 0 {
break;
}
}

give
}
}

type Input = Vec<Monkey>;

#[aoc_generator(day11)]
fn parse_input(input: &str) -> Input {
input
.split("\n\n")
.map(|m| {
let lines: Vec<&str> = m.lines().skip(1).collect();

let (_, numbers_str) = lines[0].split_once(": ").unwrap();
let items: Vec<u64> = numbers_str
.split(", ")
.map(|str| str.parse::<u64>().unwrap())
.collect();

let operation = Operation {
str: lines[1].split(" = ").collect::<Vec<&str>>()[1].into(),
};

let d = lines[2].split(" by ").collect::<Vec<&str>>()[1]
.parse::<u64>()
.unwrap();

let positive = lines[3].split("monkey ").collect::<Vec<&str>>()[1]
.parse::<usize>()
.unwrap();

let negative = lines[4].split("monkey ").collect::<Vec<&str>>()[1]
.parse::<usize>()
.unwrap();

Monkey {
items,
operation,
test: Test {
divisible: d,
target_positive: positive,
target_negative: negative,
},
inspections: 0,
}
})
.collect::<Vec<Monkey>>()
}

#[aoc(day11, part1)]
fn part1(input: &Input) -> usize {
let mut input = input.clone();

for _ in 0..20 {
for i in 0..input.len() {
let give = input[i].turn(|w| w / 3);

give.iter()
.rev()
.for_each(|(target, item)| input[*target].items.push(*item));
}
}

let mut inspections = input.iter().map(|m| m.inspections).collect::<Vec<usize>>();
inspections.sort();

inspections.iter().rev().take(2).product()
}

#[aoc(day11, part2)]
fn part2(input: &Input) -> usize {
let mut input = input.clone();
let modulus = input.iter().map(|m| m.test.divisible).product::<u64>();

for _ in 0..10000 {
for i in 0..input.len() {
let give = input[i].turn(|w| w % modulus);

give.iter()
.rev()
.for_each(|(target, item)| input[*target].items.push(*item));
}
}

let mut inspections = input.iter().map(|m| m.inspections).collect::<Vec<usize>>();
inspections.sort();

inspections.iter().rev().take(2).product()
}

#[cfg(test)]
mod tests {
use super::*;

const INPUT: &str = r##"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"##;

#[test]
fn test_part1() {
assert_eq!(10605, part1(&parse_input(INPUT)));
}

#[test]
fn test_part2() {
assert_eq!(2713310158, part2(&parse_input(INPUT)));
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ extern crate core;

pub mod day1;
pub mod day10;
pub mod day11;
pub mod day2;
pub mod day3;
pub mod day4;
Expand Down

0 comments on commit 52a8c92

Please sign in to comment.