From a576f4712fea2aed84416424a28fd3893ecfcf75 Mon Sep 17 00:00:00 2001 From: Jan-Bulthuis Date: Wed, 11 Dec 2024 11:57:54 +0100 Subject: [PATCH] day10-11 --- aoc_2024/src/day10.rs | 133 +++++++++++++++++++++++++++++++++++++++ aoc_2024/src/day11.rs | 86 +++++++++++++++++++++++++ aoc_2024/src/lib.rs | 2 + aoc_2024/src/template.rs | 33 ++++++++++ 4 files changed, 254 insertions(+) create mode 100644 aoc_2024/src/day10.rs create mode 100644 aoc_2024/src/day11.rs create mode 100644 aoc_2024/src/template.rs diff --git a/aoc_2024/src/day10.rs b/aoc_2024/src/day10.rs new file mode 100644 index 0000000..02bd6f5 --- /dev/null +++ b/aoc_2024/src/day10.rs @@ -0,0 +1,133 @@ +use std::collections::VecDeque; + +use aoc_runner_derive::{aoc, aoc_generator}; +use hashbrown::HashSet; + +type Input = (usize, usize, Vec>); + +#[aoc_generator(day10)] +fn parse(input: &str) -> Input { + let map = input + .lines() + .map(|line| line.chars().map(|c| c as u8 - 48).collect()) + .collect::>>(); + let w = map[0].len(); + let h = map.len(); + (w, h, map) +} + +#[aoc(day10, part1)] +fn part1(input: &Input) -> usize { + let mut queue = VecDeque::new(); + let mut paths = HashSet::new(); + let (w, h, map) = input; + let h = *h; + let w = *w; + (0..h).for_each(|y| { + (0..w).for_each(|x| { + if map[y][x] == 0 { + queue.push_back(((x, y), (x, y))); + } + }); + }); + + while !queue.is_empty() { + let (begin, (x, y)) = queue.pop_front().unwrap(); + let val = map[y][x]; + if val == 9 { + paths.insert((begin, (x, y))); + continue; + } + + if x > 0 && map[y][x - 1] == val + 1 { + queue.push_back((begin, (x - 1, y))); + } + if x < h - 1 && map[y][x + 1] == val + 1 { + queue.push_back((begin, (x + 1, y))); + } + if y > 0 && map[y - 1][x] == val + 1 { + queue.push_back((begin, (x, y - 1))); + } + if y < h - 1 && map[y + 1][x] == val + 1 { + queue.push_back((begin, (x, y + 1))); + } + } + + paths.len() +} + +#[aoc(day10, part2)] +fn part2(input: &Input) -> u64 { + let mut queue = VecDeque::new(); + let mut starts = Vec::new(); + let (w, h, map) = input; + let h = *h; + let w = *w; + (0..h).for_each(|y| { + (0..w).for_each(|x| { + if map[y][x] == 0 { + starts.push((x, y)); + } else if map[y][x] == 9 { + queue.push_back((x, y)); + } + }); + }); + + let mut sum = 0; + + while !queue.is_empty() { + let (x, y) = queue.pop_front().unwrap(); + let val = map[y][x]; + if val == 0 { + sum += 1; + continue; + } + + if x > 0 && map[y][x - 1] == val - 1 { + queue.push_back((x - 1, y)); + } + if x < h - 1 && map[y][x + 1] == val - 1 { + queue.push_back((x + 1, y)); + } + if y > 0 && map[y - 1][x] == val - 1 { + queue.push_back((x, y - 1)); + } + if y < h - 1 && map[y + 1][x] == val - 1 { + queue.push_back((x, y + 1)); + } + } + + sum +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1_example() { + assert_eq!(part1(&parse("0123\n1234\n8765\n9876")), 1); + assert_eq!( + part1(&parse( + "89010123\n78121874\n87430965\n96549874\n45678903\n32019012\n01329801\n10456732" + )), + 36 + ); + } + + #[test] + fn part2_example() { + assert_eq!( + part2(&parse( + ";;;;;0;\n;;4321;\n;;5;;2;\n;;6543;\n;;7;;4;\n;;8765;\n;;9;;;;" + )), + 3 + ); + assert_eq!( + part2(&parse( + "89010123\n78121874\n87430965\n96549874\n45678903\n32019012\n01329801\n10456732" + )), + 81 + ); + } +} diff --git a/aoc_2024/src/day11.rs b/aoc_2024/src/day11.rs new file mode 100644 index 0000000..b629a23 --- /dev/null +++ b/aoc_2024/src/day11.rs @@ -0,0 +1,86 @@ +use std::collections::VecDeque; + +use aoc_runner_derive::{aoc, aoc_generator}; +use hashbrown::{hash_map::Entry, HashMap}; +use nom::{ + character::complete::{space1, u64 as parse_usize}, + error::Error, + multi::separated_list1, +}; +use rayon::prelude::*; + +type Input = Vec; + +#[aoc_generator(day11)] +fn parse(input: &str) -> Input { + separated_list1(space1::<&str, Error<&str>>, parse_usize)(input) + .unwrap() + .1 + .into_iter() + .map(|v| v as usize) + .collect() +} + +#[aoc(day11, part1)] +fn part1(input: &Input) -> usize { + blink(25, input.clone()) +} + +#[aoc(day11, part2)] +fn part2(input: &Input) -> usize { + blink(75, input.clone()) +} + +fn blink(blinks: usize, input: Vec) -> usize { + let mut stones = HashMap::new(); + for stone in input { + *stones.entry(stone).or_insert(0) += 1; + } + for _ in 0..blinks { + stones = single_blink(stones); + } + stones.values().sum::() +} + +fn single_blink(stones: HashMap) -> HashMap { + let mut new_stones = HashMap::with_capacity(2 << 12); + + for (stone, count) in stones { + if stone == 0 { + *new_stones.entry(1).or_insert(0) += count; + } else { + let digits = stone.ilog10() + 1; + if digits % 2 == 0 { + let left = stone / 10usize.pow(digits / 2); + let right = stone % 10usize.pow(digits / 2); + *new_stones.entry(left).or_insert(0) += count; + *new_stones.entry(right).or_insert(0) += count; + } else { + *new_stones.entry(stone * 2024).or_insert(0) += count; + } + } + } + + new_stones +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1_example() { + assert_eq!( + part1(&parse(include_str!("../input/2024/day11.txt").trim_end())), + 203609 + ); + } + + #[test] + fn part2_example() { + assert_eq!( + part2(&parse(include_str!("../input/2024/day11.txt").trim_end())), + 240954878211138 + ); + } +} diff --git a/aoc_2024/src/lib.rs b/aoc_2024/src/lib.rs index 75d847e..adc4a0d 100644 --- a/aoc_2024/src/lib.rs +++ b/aoc_2024/src/lib.rs @@ -1,4 +1,6 @@ mod day1; +mod day10; +mod day11; mod day2; mod day3; mod day4; diff --git a/aoc_2024/src/template.rs b/aoc_2024/src/template.rs new file mode 100644 index 0000000..9deadb5 --- /dev/null +++ b/aoc_2024/src/template.rs @@ -0,0 +1,33 @@ +use aoc_runner_derive::{aoc, aoc_generator}; + +type Input = (); + +#[aoc_generator(day)] +fn parse(input: &str) -> Input { + todo!() +} + +#[aoc(day, part1)] +fn part1(input: &Input) -> usize { + todo!() +} + +// #[aoc(day, part2)] +// fn part2(input: &Input) -> usize { +// todo!() +// } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1_example() { + assert_eq!(part1(&parse("")), 0); + } + + // #[test] + // fn part2_example() { + // assert_eq!(part2(&parse("")), 0); + // } +}