From 05ab0f5813f0c491a25ced4d2aa6bb7d71b72357 Mon Sep 17 00:00:00 2001 From: red Date: Thu, 21 Mar 2024 21:31:29 +0100 Subject: [PATCH] Year 2016: Day 19 --- CHANGELOG.md | 4 +++ Cargo.toml | 2 +- NOTES_2016.md | 4 +++ README.md | 2 +- benches/year_2016.rs | 16 +++++++++++- inputs/year_2016/day_19_input | 1 + src/year_2016.rs | 10 ++++++++ src/year_2016/day_19.rs | 46 +++++++++++++++++++++++++++++++++++ 8 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 inputs/year_2016/day_19_input create mode 100644 src/year_2016/day_19.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c88efa..1949441 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.19.1] +### Added +- Solved [exercice for 2016, day 19](src/year_2016/19.rs). + ## [2016.18.1] ### Added - Solved [exercice for 2016, day 18](src/year_2016/18.rs). diff --git a/Cargo.toml b/Cargo.toml index a4cdd0c..566ffe7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "advent-rs" -version = "2016.18.1" +version = "2016.19.1" edition = "2021" authors = ["Arnaud 'red' Rouyer"] readme = "README.md" diff --git a/NOTES_2016.md b/NOTES_2016.md index 1fd10ee..42a1fb3 100644 --- a/NOTES_2016.md +++ b/NOTES_2016.md @@ -86,3 +86,7 @@ There was some confusion between all the generics, abstractions, and types, espe ## Day 18: Like a Rogue Easy come, easy go. + +## Day 19: An Elephant Named Joseph + +As easy in Rust as it was in Ruby. diff --git a/README.md b/README.md index dabd382..151a552 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 18](NOTES_2016.md) +- [2016, up to day 19](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 b205bb5..6df646e 100644 --- a/benches/year_2016.rs +++ b/benches/year_2016.rs @@ -16,6 +16,7 @@ use advent_rs::year_2016::day_15; use advent_rs::year_2016::day_16; use advent_rs::year_2016::day_17; use advent_rs::year_2016::day_18; +use advent_rs::year_2016::day_19; use criterion::{black_box, criterion_group, criterion_main, Criterion}; pub fn year_2016_day_01(c: &mut Criterion) { @@ -234,6 +235,18 @@ pub fn year_2016_day_18(c: &mut Criterion) { g2016_day_18.finish(); } +pub fn year_2016_day_19(c: &mut Criterion) { + let mut g2016_day_19 = c.benchmark_group("year_2016::day_19"); + let input_year_2016_day_19 = include_str!("../inputs/year_2016/day_19_input"); + g2016_day_19.bench_function("year_2016::day_19_v1", |b| { + b.iter(|| day_19::day_19_v1(black_box(input_year_2016_day_19))) + }); + g2016_day_19.bench_function("year_2016::day_19_v2", |b| { + b.iter(|| day_19::day_19_v2(black_box(input_year_2016_day_19))) + }); + g2016_day_19.finish(); +} + criterion_group!( benches, year_2016_day_01, @@ -253,6 +266,7 @@ criterion_group!( year_2016_day_15, year_2016_day_16, year_2016_day_17, - year_2016_day_18 + year_2016_day_18, + year_2016_day_19 ); criterion_main!(benches); diff --git a/inputs/year_2016/day_19_input b/inputs/year_2016/day_19_input new file mode 100644 index 0000000..a452141 --- /dev/null +++ b/inputs/year_2016/day_19_input @@ -0,0 +1 @@ +3012210 \ No newline at end of file diff --git a/src/year_2016.rs b/src/year_2016.rs index 9db068b..d40b2d2 100644 --- a/src/year_2016.rs +++ b/src/year_2016.rs @@ -21,6 +21,7 @@ pub mod day_15; pub mod day_16; pub mod day_17; pub mod day_18; +pub mod day_19; pub fn solve(day: u8, part: u8, input: impl Into) -> Option { if part != 1 && part != 2 { @@ -45,6 +46,8 @@ pub fn solve(day: u8, part: u8, input: impl Into) -> Option { 15 => Some(format!("{}", day_15::day_15(part, input))), 16 => Some(format!("{}", day_16::day_16(part, input))), 17 => Some(format!("{}", day_17::day_17(part, input))), + 18 => Some(format!("{}", day_18::day_18(part, input))), + 19 => Some(format!("{}", day_19::day_19(part, input))), _ => None, } } @@ -187,4 +190,11 @@ mod tests { assert_eq!(day_18::day_18_v1(input), 1926); assert_eq!(day_18::day_18_v2(input), 19_986_699); } + + #[test] + fn day_19() { + let input = include_str!("../inputs/year_2016/day_19_input"); + assert_eq!(day_19::day_19_v1(input), 1_830_117); + assert_eq!(day_19::day_19_v2(input), 1_417_887); + } } diff --git a/src/year_2016/day_19.rs b/src/year_2016/day_19.rs new file mode 100644 index 0000000..a08739e --- /dev/null +++ b/src/year_2016/day_19.rs @@ -0,0 +1,46 @@ +use itertools::Itertools; +use std::collections::VecDeque; + +pub fn day_19_v1(input: impl Into) -> u32 { + let number = input.into().parse::().unwrap(); + let mut binary = format!("{number:b}").chars().collect_vec(); + binary.rotate_left(1); + + u32::from_str_radix(&binary.iter().collect::(), 2).unwrap() +} + +pub fn day_19_v2(input: impl Into) -> u32 { + let number = input.into().parse::().unwrap(); + let mid = (number + 1) / 2; + let mut arr_v1: VecDeque = (1..mid).collect(); + let mut arr_v2: VecDeque = (mid..(number + 1)).collect(); + loop { + if arr_v2.len() >= arr_v1.len() { + arr_v2.pop_front(); + if arr_v2.is_empty() { + return arr_v1[0]; + } + } else { + arr_v1.pop_back(); + } + arr_v1.push_back(arr_v2.pop_front().unwrap()); + arr_v2.push_back(arr_v1.pop_front().unwrap()); + } +} + +solvable!(day_19, day_19_v1, day_19_v2, u32); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn works_with_samples_v1() { + assert_eq!(day_19_v1("5"), 3); + } + + #[test] + fn works_with_samples_v2() { + assert_eq!(day_19_v2("5"), 2); + } +}