diff --git a/README.md b/README.md index 73a7d6a0..c13d08a8 100644 --- a/README.md +++ b/README.md @@ -15,4 +15,4 @@ Development occurs in language-specific directories: |[Day8.hs](hs/src/Day8.hs)|[Day8.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day8.kt)|[day8.py](py/aoc2024/day8.py)|[day8.rs](rs/src/day8.rs)| |[Day9.hs](hs/src/Day9.hs)|[Day9.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day9.kt)|[day9.py](py/aoc2024/day9.py)|[day9.rs](rs/src/day9.rs)| |[Day10.hs](hs/src/Day10.hs)|[Day10.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day10.kt)|[day10.py](py/aoc2024/day10.py)|[day10.rs](rs/src/day10.rs)| -|[Day11.hs](hs/src/Day11.hs)|[Day11.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day11.kt)|[day11.py](py/aoc2024/day11.py)|| +|[Day11.hs](hs/src/Day11.hs)|[Day11.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day11.kt)|[day11.py](py/aoc2024/day11.py)|[day11.rs](rs/src/day11.rs)| diff --git a/rs/benches/criterion.rs b/rs/benches/criterion.rs index 42bb1ec2..f36e462e 100644 --- a/rs/benches/criterion.rs +++ b/rs/benches/criterion.rs @@ -1,4 +1,4 @@ -use aoc2024::{day1, day10, day2, day3, day4, day5, day6, day7, day8, day9}; +use aoc2024::{day1, day10, day11, day2, day3, day4, day5, day6, day7, day8, day9}; use criterion::{black_box, Criterion}; use std::env; use std::fs; @@ -74,6 +74,12 @@ fn aoc2024_bench(c: &mut Criterion) -> io::Result<()> { g.bench_function("part 2", |b| b.iter(|| day10::part2(black_box(&data)))); g.finish(); + let data = get_day_input(11)?; + let mut g = c.benchmark_group("day 11"); + g.bench_function("part 1", |b| b.iter(|| day11::part1(black_box(&data)))); + g.bench_function("part 2", |b| b.iter(|| day11::part2(black_box(&data)))); + g.finish(); + Ok(()) } diff --git a/rs/src/day11.rs b/rs/src/day11.rs new file mode 100644 index 00000000..962f7c10 --- /dev/null +++ b/rs/src/day11.rs @@ -0,0 +1,74 @@ +use std::collections::BTreeMap; +use std::num::ParseIntError; + +pub fn part1(data: &str) -> Result { + solve(data, 25) +} + +pub fn part2(data: &str) -> Result { + solve(data, 75) +} + +fn solve(data: &str, n: usize) -> Result { + Ok((0..n) + .fold( + { + let mut counts = BTreeMap::new(); + for word in data.split_ascii_whitespace() { + counts + .entry(word.parse::()?) + .and_modify(|e| *e += 1) + .or_insert(1u64); + } + counts + }, + |counts, _| { + let mut next = BTreeMap::new(); + for (num, count) in counts { + if num == 0 { + next.entry(1).and_modify(|e| *e += count).or_insert(count); + } else { + let length = num.ilog10() + 1; + if length % 2 == 0 { + let divisor = 10u64.pow(length / 2); + next.entry(num / divisor) + .and_modify(|e| *e += count) + .or_insert(count); + next.entry(num % divisor) + .and_modify(|e| *e += count) + .or_insert(count); + } else { + next.entry(2024 * num) + .and_modify(|e| *e += count) + .or_insert(count); + } + } + } + next + }, + ) + .into_values() + .sum()) +} + +#[cfg(test)] +mod tests { + use super::*; + use indoc::indoc; + use pretty_assertions::assert_eq; + + static EXAMPLE_1: &str = indoc! {" + 0 1 10 99 999 + "}; + + static EXAMPLE_2: &str = indoc! {" + 125 17 + "}; + + #[test] + fn part1_examples() { + assert_eq!(Ok(7), solve(EXAMPLE_1, 1)); + assert_eq!(Ok(22), solve(EXAMPLE_2, 6)); + assert_eq!(Ok(55312), solve(EXAMPLE_2, 25)); + } +} diff --git a/rs/src/lib.rs b/rs/src/lib.rs index bcca163d..737f5f66 100644 --- a/rs/src/lib.rs +++ b/rs/src/lib.rs @@ -1,5 +1,6 @@ pub mod day1; pub mod day10; +pub mod day11; pub mod day2; pub mod day3; pub mod day4; diff --git a/rs/src/main.rs b/rs/src/main.rs index 21576807..e120e059 100644 --- a/rs/src/main.rs +++ b/rs/src/main.rs @@ -1,5 +1,5 @@ use anyhow::anyhow; -use aoc2024::{day1, day10, day2, day3, day4, day5, day6, day7, day8, day9}; +use aoc2024::{day1, day10, day11, day2, day3, day4, day5, day6, day7, day8, day9}; use std::collections::HashSet; use std::env; use std::fs; @@ -97,5 +97,13 @@ fn main() -> anyhow::Result<()> { println!(); } + if args.is_empty() || args.contains("11") { + println!("Day 11"); + let data = get_day_input(11)?; + println!("{:?}", day11::part1(&data)?); + println!("{:?}", day11::part2(&data)?); + println!(); + } + Ok(()) }