diff --git a/aoc2020/aoc2020_bench/benches/aoc2020_bench.rs b/aoc2020/aoc2020_bench/benches/aoc2020_bench.rs index 6e04bee..26eb1e2 100644 --- a/aoc2020/aoc2020_bench/benches/aoc2020_bench.rs +++ b/aoc2020/aoc2020_bench/benches/aoc2020_bench.rs @@ -24,6 +24,7 @@ use aoc2020::day21; use aoc2020::day22; use aoc2020::day23; use aoc2020::day24; +use aoc2020::day25; fn aoc2020_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -50,6 +51,7 @@ fn aoc2020_all(c: &mut Criterion) { c.bench_function("day22", |b| b.iter(|| day22::run().unwrap())); c.bench_function("day23", |b| b.iter(|| day23::run().unwrap())); c.bench_function("day24", |b| b.iter(|| day24::run().unwrap())); + c.bench_function("day25", |b| b.iter(|| day25::run().unwrap())); } criterion_group! { diff --git a/aoc2020/input/day25.txt b/aoc2020/input/day25.txt new file mode 100644 index 0000000..1e40343 --- /dev/null +++ b/aoc2020/input/day25.txt @@ -0,0 +1,2 @@ +12090988 +240583 diff --git a/aoc2020/input/day25_provided.txt b/aoc2020/input/day25_provided.txt new file mode 100644 index 0000000..9cbfc23 --- /dev/null +++ b/aoc2020/input/day25_provided.txt @@ -0,0 +1,2 @@ +5764801 +17807724 diff --git a/aoc2020/src/day25.rs b/aoc2020/src/day25.rs new file mode 100644 index 0000000..81539d8 --- /dev/null +++ b/aoc2020/src/day25.rs @@ -0,0 +1,77 @@ +use std::fmt::Write; + +use anyhow::{Context, Result}; + +const INPUT: &str = include_str!("../input/day25.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + + Ok(res) +} + +const PUB_KEY_SUBJECT: u64 = 7; + +// - Set the value to itself multiplied by the subject number. +// - Set the value to the remainder after dividing the value by 20201227. +fn transform(mut value: u64, subject: u64) -> u64 { + value *= subject; + + value % 20201227 +} + +fn find_loop_size(pub_key: u64) -> usize { + let mut value = 1; + for i in 1.. { + value = transform(value, PUB_KEY_SUBJECT); + + if value == pub_key { + return i; + } + } + + unreachable!() +} + +fn part1(input: &str) -> Result { + let mut lines = input.lines(); + + let card_pub_key: u64 = lines + .next() + .context("no public key found for card")? + .parse()?; + let door_pub_key: u64 = lines + .next() + .context("no public key found for door")? + .parse()?; + + let card_loop_size = find_loop_size(card_pub_key); + + let mut encryption_key = 1; + for _ in 0..card_loop_size { + encryption_key = transform(encryption_key, door_pub_key); + } + + Ok(encryption_key) +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day25_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(find_loop_size(5764801), 8); + assert_eq!(find_loop_size(17807724), 11); + assert_eq!(part1(PROVIDED).unwrap(), 14897079); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 3015200); + } +} diff --git a/aoc2020/src/lib.rs b/aoc2020/src/lib.rs index 0ec7fd3..b611f39 100644 --- a/aoc2020/src/lib.rs +++ b/aoc2020/src/lib.rs @@ -24,3 +24,4 @@ pub mod day21; pub mod day22; pub mod day23; pub mod day24; +pub mod day25; diff --git a/aoc2020/src/main.rs b/aoc2020/src/main.rs index 6b1ca8e..38d5dbe 100644 --- a/aoc2020/src/main.rs +++ b/aoc2020/src/main.rs @@ -26,6 +26,7 @@ use aoc2020::day21; use aoc2020::day22; use aoc2020::day23; use aoc2020::day24; +use aoc2020::day25; fn main() -> Result<()> { let days: &[DayFunc] = &[ @@ -53,6 +54,7 @@ fn main() -> Result<()> { day22::run, day23::run, day24::run, + day25::run, ]; aoc::run(days)