Refactoring, Added day11
This commit is contained in:
parent
5366017271
commit
6f20f87a36
133
src/day11/1.rs
Normal file
133
src/day11/1.rs
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
#![feature(test)]
|
||||||
|
|
||||||
|
use std::{cmp::Reverse, rc::Rc};
|
||||||
|
extern crate test;
|
||||||
|
|
||||||
|
const INPUTS: [&str; 2] = [include_str!("./sample.txt"), include_str!("./input.txt")];
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Monkey {
|
||||||
|
items: Vec<usize>,
|
||||||
|
operation: Rc<Box<dyn Fn(usize) -> usize>>,
|
||||||
|
div_by_test: usize,
|
||||||
|
if_true: usize,
|
||||||
|
if_false: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse(input: &'static str) -> Vec<Monkey> {
|
||||||
|
input
|
||||||
|
.split("\n\n")
|
||||||
|
.filter(|c| !c.is_empty())
|
||||||
|
.map(|set| {
|
||||||
|
let mut lines = set.lines().skip(1);
|
||||||
|
|
||||||
|
let sitems: Vec<usize> = lines
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.split(',')
|
||||||
|
.map(|c| {
|
||||||
|
c.chars()
|
||||||
|
.filter(|c| c.is_numeric())
|
||||||
|
.fold(0, |a, x| (a * 10) + (x as u8 - b'0') as usize)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let op = lines.next().unwrap();
|
||||||
|
let nop = op
|
||||||
|
.bytes()
|
||||||
|
.filter(|c| (b'0'..=b'9').contains(c))
|
||||||
|
.fold(0, |a, x| (a * 10) + (x - b'0') as usize);
|
||||||
|
|
||||||
|
let op = move |old: usize| -> usize {
|
||||||
|
if op.contains("old * old") {
|
||||||
|
old * old
|
||||||
|
} else if op.contains("old +") {
|
||||||
|
old + nop
|
||||||
|
} else if op.contains("old *") {
|
||||||
|
old * nop
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let test = lines
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.bytes()
|
||||||
|
.filter(|c| (b'0'..=b'9').contains(c))
|
||||||
|
.fold(0, |a, x| (a * 10) + (x - b'0') as usize);
|
||||||
|
|
||||||
|
let true_result = lines
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.bytes()
|
||||||
|
.filter(|c| (b'0'..=b'9').contains(c))
|
||||||
|
.fold(0, |a, x| (a * 10) + (x - b'0') as usize);
|
||||||
|
|
||||||
|
let false_result = lines
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.bytes()
|
||||||
|
.filter(|c| (b'0'..=b'9').contains(c))
|
||||||
|
.fold(0, |a, x| (a * 10) + (x - b'0') as usize);
|
||||||
|
|
||||||
|
Monkey {
|
||||||
|
items: sitems,
|
||||||
|
operation: Rc::new(Box::new(op)),
|
||||||
|
div_by_test: test,
|
||||||
|
if_true: true_result,
|
||||||
|
if_false: false_result,
|
||||||
|
}
|
||||||
|
//
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
for input in INPUTS.iter() {
|
||||||
|
let output = parse(input);
|
||||||
|
let score = solution(output);
|
||||||
|
println!("{}", score);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solution(mut input: Vec<Monkey>) -> usize {
|
||||||
|
let mlen = input.len();
|
||||||
|
let mut activity = vec![0; mlen];
|
||||||
|
|
||||||
|
for _ in 0..20 {
|
||||||
|
for i in 0..mlen {
|
||||||
|
let monkey = &input[i].clone();
|
||||||
|
let ilen = monkey.items.len();
|
||||||
|
|
||||||
|
for j in 0..ilen {
|
||||||
|
let item = monkey.items[j];
|
||||||
|
|
||||||
|
let newwlevel = (monkey.operation)(item);
|
||||||
|
let calmed_down_level = newwlevel / 3;
|
||||||
|
|
||||||
|
if calmed_down_level % monkey.div_by_test == 0 {
|
||||||
|
input[monkey.if_true].items.push(calmed_down_level);
|
||||||
|
} else {
|
||||||
|
input[monkey.if_false].items.push(calmed_down_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
activity[i] += 1;
|
||||||
|
}
|
||||||
|
input[i].items.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
activity.select_nth_unstable_by_key(1, |c| Reverse(*c));
|
||||||
|
|
||||||
|
activity[0] * activity[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn solution_bench(b: &mut test::Bencher) {
|
||||||
|
b.iter(|| {
|
||||||
|
let input = parse(INPUTS[1]);
|
||||||
|
let result = solution(input);
|
||||||
|
test::black_box(result);
|
||||||
|
})
|
||||||
|
}
|
146
src/day11/2.rs
Normal file
146
src/day11/2.rs
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
#![feature(test)]
|
||||||
|
|
||||||
|
use std::cmp::Reverse;
|
||||||
|
extern crate test;
|
||||||
|
|
||||||
|
const INPUTS: [&str; 2] = [include_str!("./sample.txt"), include_str!("./input.txt")];
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Monkey {
|
||||||
|
items: Vec<usize>,
|
||||||
|
operation: Operation,
|
||||||
|
div_by_test: usize,
|
||||||
|
if_true: usize,
|
||||||
|
if_false: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Copy)]
|
||||||
|
enum Operation {
|
||||||
|
MulOld,
|
||||||
|
MulNop(usize),
|
||||||
|
AddNop(usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Operation {
|
||||||
|
fn apply(&self, v: usize) -> usize {
|
||||||
|
match self {
|
||||||
|
Operation::MulOld => v * v,
|
||||||
|
Operation::MulNop(i) => v * i,
|
||||||
|
Operation::AddNop(i) => v + i,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse(input: &'static str) -> (Vec<Monkey>, usize) {
|
||||||
|
let mut lcm = 1;
|
||||||
|
let output = input
|
||||||
|
.split("\n\n")
|
||||||
|
.filter(|c| !c.is_empty())
|
||||||
|
.map(|set| {
|
||||||
|
let mut lines = set.lines().skip(1);
|
||||||
|
|
||||||
|
let sitems: Vec<usize> = lines.next().unwrap()[18..]
|
||||||
|
.split(',')
|
||||||
|
.map(|c| {
|
||||||
|
c.bytes()
|
||||||
|
.filter(|&c| c != b' ')
|
||||||
|
.fold(0, |a, x| (a * 10) + (x - b'0') as usize)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let op = match lines.next().unwrap()[23..].split_at(1) {
|
||||||
|
("*", " old") => Operation::MulOld,
|
||||||
|
("+", v) => Operation::AddNop(
|
||||||
|
v[1..]
|
||||||
|
.bytes()
|
||||||
|
.fold(0, |a, x| (a * 10) + (x - b'0') as usize),
|
||||||
|
),
|
||||||
|
("*", v) => Operation::MulNop(
|
||||||
|
v[1..]
|
||||||
|
.bytes()
|
||||||
|
.fold(0, |a, x| (a * 10) + (x - b'0') as usize),
|
||||||
|
),
|
||||||
|
(_, _) => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let test = lines.next().unwrap()[21..]
|
||||||
|
.bytes()
|
||||||
|
.fold(0, |a, x| (a * 10) + (x - b'0') as usize);
|
||||||
|
|
||||||
|
let true_result = lines.next().unwrap()[29..]
|
||||||
|
.bytes()
|
||||||
|
.fold(0, |a, x| (a * 10) + (x - b'0') as usize);
|
||||||
|
|
||||||
|
let false_result = lines.next().unwrap()[30..]
|
||||||
|
.bytes()
|
||||||
|
.fold(0, |a, x| (a * 10) + (x - b'0') as usize);
|
||||||
|
|
||||||
|
lcm = lcm * test / gcd(lcm, test);
|
||||||
|
|
||||||
|
Monkey {
|
||||||
|
items: sitems,
|
||||||
|
operation: op,
|
||||||
|
div_by_test: test,
|
||||||
|
if_true: true_result,
|
||||||
|
if_false: false_result,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
(output, lcm)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
for input in INPUTS.iter() {
|
||||||
|
let output = parse(input);
|
||||||
|
let score = solution(output.0, output.1);
|
||||||
|
println!("{}", score);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solution(mut input: Vec<Monkey>, lcm: usize) -> usize {
|
||||||
|
let mlen = input.len();
|
||||||
|
let mut activity = [0; 8];
|
||||||
|
|
||||||
|
for _ in 0..10000 {
|
||||||
|
for i in 0..mlen {
|
||||||
|
activity[i] += input[i].items.len();
|
||||||
|
let if_true = input[i].if_true;
|
||||||
|
let if_false = input[i].if_false;
|
||||||
|
let operation = input[i].operation;
|
||||||
|
let div_by_test = input[i].div_by_test;
|
||||||
|
|
||||||
|
while let Some(item) = input[i].items.pop() {
|
||||||
|
let newwlevel = operation.apply(item);
|
||||||
|
let newwlevel = newwlevel % lcm;
|
||||||
|
|
||||||
|
if newwlevel % div_by_test == 0 {
|
||||||
|
input[if_true].items.push(newwlevel);
|
||||||
|
} else {
|
||||||
|
input[if_false].items.push(newwlevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
activity.select_nth_unstable_by_key(1, |c| Reverse(*c));
|
||||||
|
|
||||||
|
activity[0] * activity[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn solution_bench(b: &mut test::Bencher) {
|
||||||
|
b.iter(|| {
|
||||||
|
let input = parse(INPUTS[1]);
|
||||||
|
let result = solution(input.0, input.1);
|
||||||
|
test::black_box(result);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
const fn gcd(a: usize, b: usize) -> usize {
|
||||||
|
if b == 0 {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
gcd(b, a % b)
|
||||||
|
}
|
56
src/day11/input.txt
Normal file
56
src/day11/input.txt
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
Monkey 0:
|
||||||
|
Starting items: 83, 97, 95, 67
|
||||||
|
Operation: new = old * 19
|
||||||
|
Test: divisible by 17
|
||||||
|
If true: throw to monkey 2
|
||||||
|
If false: throw to monkey 7
|
||||||
|
|
||||||
|
Monkey 1:
|
||||||
|
Starting items: 71, 70, 79, 88, 56, 70
|
||||||
|
Operation: new = old + 2
|
||||||
|
Test: divisible by 19
|
||||||
|
If true: throw to monkey 7
|
||||||
|
If false: throw to monkey 0
|
||||||
|
|
||||||
|
Monkey 2:
|
||||||
|
Starting items: 98, 51, 51, 63, 80, 85, 84, 95
|
||||||
|
Operation: new = old + 7
|
||||||
|
Test: divisible by 7
|
||||||
|
If true: throw to monkey 4
|
||||||
|
If false: throw to monkey 3
|
||||||
|
|
||||||
|
Monkey 3:
|
||||||
|
Starting items: 77, 90, 82, 80, 79
|
||||||
|
Operation: new = old + 1
|
||||||
|
Test: divisible by 11
|
||||||
|
If true: throw to monkey 6
|
||||||
|
If false: throw to monkey 4
|
||||||
|
|
||||||
|
Monkey 4:
|
||||||
|
Starting items: 68
|
||||||
|
Operation: new = old * 5
|
||||||
|
Test: divisible by 13
|
||||||
|
If true: throw to monkey 6
|
||||||
|
If false: throw to monkey 5
|
||||||
|
|
||||||
|
Monkey 5:
|
||||||
|
Starting items: 60, 94
|
||||||
|
Operation: new = old + 5
|
||||||
|
Test: divisible by 3
|
||||||
|
If true: throw to monkey 1
|
||||||
|
If false: throw to monkey 0
|
||||||
|
|
||||||
|
Monkey 6:
|
||||||
|
Starting items: 81, 51, 85
|
||||||
|
Operation: new = old * old
|
||||||
|
Test: divisible by 5
|
||||||
|
If true: throw to monkey 5
|
||||||
|
If false: throw to monkey 1
|
||||||
|
|
||||||
|
Monkey 7:
|
||||||
|
Starting items: 98, 81, 63, 65, 84, 71, 84
|
||||||
|
Operation: new = old + 3
|
||||||
|
Test: divisible by 2
|
||||||
|
If true: throw to monkey 2
|
||||||
|
If false: throw to monkey 3
|
||||||
|
|
27
src/day11/sample.txt
Normal file
27
src/day11/sample.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
|
Loading…
Reference in New Issue
Block a user