From 510966ecedca16612c90ba96ca1a162cdca84bc2 Mon Sep 17 00:00:00 2001 From: red Date: Tue, 19 Mar 2024 19:56:33 +0100 Subject: [PATCH] Year 2016: Day 15 --- CHANGELOG.md | 4 +++ Cargo.toml | 2 +- NOTES_2016.md | 20 +++++++++++++ README.md | 2 +- benches/year_2016.rs | 16 ++++++++++- inputs/year_2016/day_15_input | 6 ++++ src/year_2016.rs | 9 ++++++ src/year_2016/day_15.rs | 54 +++++++++++++++++++++++++++++++++++ 8 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 inputs/year_2016/day_15_input create mode 100644 src/year_2016/day_15.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 203147f..cdbc817 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ Of note: - The changelog 2015.5.2 has been rewritten from each commit content. - This file may be amended entirely in the future to adhere to the [GNU Changelog style](https://www.gnu.org/prep/standards/html_node/Style-of-Change-Logs.html#Style-of-Change-Logs) +## [2016.15.1] +### Added +- Solved [exercice for 2016, day 15](src/year_2016/day_15.rs). + ## [2016.14.1] ### Added - Solved [exercice for 2016, day 14](src/year_2016/day_14.rs). diff --git a/Cargo.toml b/Cargo.toml index 7ea8194..3a9cc53 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "advent-rs" -version = "2016.14.1" +version = "2016.15.1" edition = "2021" authors = ["Arnaud 'red' Rouyer"] readme = "README.md" diff --git a/NOTES_2016.md b/NOTES_2016.md index 6a80c96..e7c5b8a 100644 --- a/NOTES_2016.md +++ b/NOTES_2016.md @@ -50,3 +50,23 @@ Looking at it carefully proved very smart: both galenelias and me lost too much ## Day 10: Balance Bots This exercise got me to face the worst part of Rust: iterating over a hashmap while mutating it. + +## Day 11: Radioisotope Thermoelectric Generators + +Ugh. I hated this just as much as the first time. + +## Day 12: Leonardo's Monorail + +Finally, we are back into interesting exercises! + +## Day 13: A Maze of Twisty Little Cubicles + +... + +## Day 14: One-Time Pad + +Computing MD5 hashes is never interesting. + +## Day 15: Timing is Everything + +Finally, something funny to do. diff --git a/README.md b/README.md index 6dda13c..f2fdb79 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ As I said, [Consistency is hard](https://github.com/joshleaves/advent-rb), and I I'm also adding notes that may be useful if you're (like me) discovering Rust: - [2015, complete!](NOTES_2015.md) -- [2016, up to day 14](NOTES_2016.md) +- [2016, up to day 15](NOTES_2016.md) # Regarding style rules I'm gonna use a mix of what `cargo fmt` does, with some stuff that feels more natural to me. diff --git a/benches/year_2016.rs b/benches/year_2016.rs index 76d70ff..04a8022 100644 --- a/benches/year_2016.rs +++ b/benches/year_2016.rs @@ -12,6 +12,7 @@ use advent_rs::year_2016::day_11; use advent_rs::year_2016::day_12; use advent_rs::year_2016::day_13; use advent_rs::year_2016::day_14; +use advent_rs::year_2016::day_15; use criterion::{black_box, criterion_group, criterion_main, Criterion}; pub fn year_2016_day_01(c: &mut Criterion) { @@ -182,6 +183,18 @@ pub fn year_2016_day_14(c: &mut Criterion) { g2016_day_14.finish(); } +pub fn year_2016_day_15(c: &mut Criterion) { + let mut g2016_day_15 = c.benchmark_group("year_2016::day_15"); + let input_year_2016_day_15 = include_str!("../inputs/year_2016/day_15_input"); + g2016_day_15.bench_function("year_2016::day_15_v1", |b| { + b.iter(|| day_15::day_15_v1(black_box(input_year_2016_day_15))) + }); + g2016_day_15.bench_function("year_2016::day_15_v2", |b| { + b.iter(|| day_15::day_15_v2(black_box(input_year_2016_day_15))) + }); + g2016_day_15.finish(); +} + criterion_group!( benches, year_2016_day_01, @@ -197,6 +210,7 @@ criterion_group!( year_2016_day_11, year_2016_day_12, year_2016_day_13, - year_2016_day_14 + year_2016_day_14, + year_2016_day_15 ); criterion_main!(benches); diff --git a/inputs/year_2016/day_15_input b/inputs/year_2016/day_15_input new file mode 100644 index 0000000..396cee2 --- /dev/null +++ b/inputs/year_2016/day_15_input @@ -0,0 +1,6 @@ +Disc #1 has 13 positions; at time=0, it is at position 10. +Disc #2 has 17 positions; at time=0, it is at position 15. +Disc #3 has 19 positions; at time=0, it is at position 17. +Disc #4 has 7 positions; at time=0, it is at position 1. +Disc #5 has 5 positions; at time=0, it is at position 0. +Disc #6 has 3 positions; at time=0, it is at position 1. diff --git a/src/year_2016.rs b/src/year_2016.rs index ce13c76..9c016ca 100644 --- a/src/year_2016.rs +++ b/src/year_2016.rs @@ -17,6 +17,7 @@ pub mod day_11; pub mod day_12; pub mod day_13; pub mod day_14; +pub mod day_15; pub fn solve(day: u8, part: u8, input: impl Into) -> Option { if part != 1 && part != 2 { @@ -38,6 +39,7 @@ pub fn solve(day: u8, part: u8, input: impl Into) -> Option { 12 => Some(format!("{}", day_12::day_12(part, input))), 13 => Some(format!("{}", day_13::day_13(part, input))), 14 => Some(format!("{}", day_14::day_14(part, input))), + 15 => Some(format!("{}", day_15::day_15(part, input))), _ => None, } } @@ -152,4 +154,11 @@ mod tests { assert_eq!(day_14::day_14_v1(input), 25_427); assert_eq!(day_14::day_14_v2(input), 22_045); } + + #[test] + fn day_15() { + let input = include_str!("../inputs/year_2016/day_15_input"); + assert_eq!(day_15::day_15_v1(input), 203_660); + assert_eq!(day_15::day_15_v2(input), 2_408_135); + } } diff --git a/src/year_2016/day_15.rs b/src/year_2016/day_15.rs new file mode 100644 index 0000000..2c8ac50 --- /dev/null +++ b/src/year_2016/day_15.rs @@ -0,0 +1,54 @@ +fn parse_disc(input: &str) -> (u32, u32, u32) { + let words: Vec<&str> = input.split_whitespace().collect(); + let disc = words[1].strip_prefix('#').unwrap().parse::().unwrap(); + let npos = words[3].parse::().unwrap(); + let spos = words[11].strip_suffix('.').unwrap().parse::().unwrap(); + + (disc, npos, spos) +} + +fn spin_the_discs(discs: Vec<(u32, u32, u32)>) -> u32 { + let mut period = 1; + let mut time = 0; + for (disc, npos, spos) in discs.iter() { + while ((time + disc + spos) % npos) != 0 { + time += period; + } + period *= npos; + } + + time +} + +pub fn day_15_v1(input: impl Into) -> u32 { + let mut discs: Vec<(u32, u32, u32)> = vec![]; + for line in input.into().lines() { + discs.push(parse_disc(line)); + } + + spin_the_discs(discs) +} + +pub fn day_15_v2(input: impl Into) -> u32 { + let mut discs: Vec<(u32, u32, u32)> = vec![]; + for line in input.into().lines() { + discs.push(parse_disc(line)); + } + discs.push(((discs.len() + 1) as u32, 11, 0)); + + spin_the_discs(discs) +} + +solvable!(day_15, day_15_v1, day_15_v2, u32); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn works_with_samples_v1() { + let sample_one = "Disc #1 has 5 positions; at time=0, it is at position 4.\n\ + Disc #2 has 2 positions; at time=0, it is at position 1."; + assert_eq!(day_15_v1(sample_one), 5); + } +}