This commit is contained in:
Jan-Bulthuis 2024-12-11 11:57:54 +01:00
parent f96ab9d93b
commit a576f4712f
4 changed files with 254 additions and 0 deletions

133
aoc_2024/src/day10.rs Normal file
View File

@ -0,0 +1,133 @@
use std::collections::VecDeque;
use aoc_runner_derive::{aoc, aoc_generator};
use hashbrown::HashSet;
type Input = (usize, usize, Vec<Vec<u8>>);
#[aoc_generator(day10)]
fn parse(input: &str) -> Input {
let map = input
.lines()
.map(|line| line.chars().map(|c| c as u8 - 48).collect())
.collect::<Vec<Vec<u8>>>();
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
);
}
}

86
aoc_2024/src/day11.rs Normal file
View File

@ -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<usize>;
#[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>) -> 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::<usize>()
}
fn single_blink(stones: HashMap<usize, usize>) -> HashMap<usize, usize> {
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
);
}
}

View File

@ -1,4 +1,6 @@
mod day1; mod day1;
mod day10;
mod day11;
mod day2; mod day2;
mod day3; mod day3;
mod day4; mod day4;

33
aoc_2024/src/template.rs Normal file
View File

@ -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("<EXAMPLE>")), 0);
}
// #[test]
// fn part2_example() {
// assert_eq!(part2(&parse("<EXAMPLE>")), 0);
// }
}