Skip to content

Commit e0049a0

Browse files
committed
solve: day18
1 parent b62b59d commit e0049a0

File tree

6 files changed

+120
-9
lines changed

6 files changed

+120
-9
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
resolver = "2"
33
members = [
44
"utils",
5-
"aoc_derive", "day1", "day2", "day3", "day4", "day5", "day6", "day7", "day8", "day9", "day10", "day11", "day12", "day13", "day14", "day15", "day16", "day17",
5+
"aoc_derive", "day1", "day2", "day3", "day4", "day5", "day6", "day7", "day8", "day9", "day10", "day11", "day12", "day13", "day14", "day15", "day16", "day17", "day18",
66
]
77

88
[workspace.dependencies]

aoc_derive/src/lib.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@ use syn::{parse_macro_input, Expr, ExprLit, Lit};
44

55
// Uses syn (v2) to parse the macro #[aoc_main(1)]
66
#[proc_macro_attribute]
7-
pub fn aoc_main(_args: TokenStream, item: TokenStream) -> TokenStream {
7+
pub fn aoc_main(args: TokenStream, item: TokenStream) -> TokenStream {
88
let solve_fn = parse_macro_input!(item as syn::ItemFn);
99

10+
let args = proc_macro2::TokenStream::from(args);
11+
12+
//let args = parse_macro_input!(args with Punctuated::<Meta, syn::Token![,]>::parse_terminated);
13+
1014
let solve_fn_identifier = solve_fn.sig.ident.clone();
1115

1216
quote! {
@@ -15,7 +19,7 @@ pub fn aoc_main(_args: TokenStream, item: TokenStream) -> TokenStream {
1519
fn main() {
1620
let input_file = std::env::args().nth(1).expect("Expect input file as first argument");
1721
let start_time = std::time::Instant::now();
18-
let solution: Solution = #solve_fn_identifier(Input::new(&input_file)).into();
22+
let solution: Solution = #solve_fn_identifier(Input::new(&input_file), #args).into();
1923
println!("{}", solution);
2024
println!("Time: {:.1?}", start_time.elapsed());
2125
solution.copy_to_clipboard();

day18/Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "day18"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
[dependencies]
7+
aoc_derive.path = '../aoc_derive'
8+
utils.path = '../utils'
9+
derive_more.workspace = true
10+
itertools.workspace = true
11+
lazy-regex.workspace = true
12+
parse-display.workspace = true
13+
rayon.workspace = true
14+
regex.workspace = true
15+
num.workspace = true
16+
17+
[dev-dependencies]
18+
pretty_assertions.workspace = true

day18/src/main.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
use std::iter::repeat_n;
2+
3+
use aoc_derive::aoc_main;
4+
use derive_more::derive::{Deref, DerefMut, From};
5+
use graphs::{UnweightedGraph, bfs};
6+
use grid::Grid;
7+
use math::Vec2D;
8+
use utils::*;
9+
10+
#[derive(Debug, Clone, Deref, DerefMut, From)]
11+
struct Map(Grid<char>);
12+
13+
impl UnweightedGraph for Map {
14+
type Node = Vec2D;
15+
16+
fn neighbors<'a, 'b: 'a>(&'a self, node: &'b Vec2D) -> impl Iterator<Item = Vec2D> + 'a {
17+
self.orthogonal_neighbors(node).filter(|n| self.get(*n) == Some(&'.'))
18+
}
19+
}
20+
21+
#[aoc_main(70, 1024)]
22+
fn solve(input: Input, size: usize, num_bytes: usize) -> impl Into<Solution> {
23+
let mut map = Map::from(repeat_n(repeat_n('.', size + 1), size + 1).collect::<Grid<char>>());
24+
let mut bytes = input.lines().map(extract_two_numbers);
25+
26+
let (start, end) = ((0, 0), (size, size));
27+
28+
let part1 = {
29+
let mut map = map.clone();
30+
for byte in bytes.clone().take(num_bytes) {
31+
map[byte] = '#';
32+
}
33+
34+
bfs(&map, start, end).distance.unwrap()
35+
};
36+
37+
let part2 = bytes
38+
.find(|&byte| {
39+
map[byte] = '#';
40+
bfs(&map, start, end).distance.is_none()
41+
})
42+
.unwrap();
43+
44+
(part1, format!("{},{}", part2.x, part2.y))
45+
}
46+
47+
#[cfg(test)]
48+
mod tests {
49+
use super::*;
50+
#[test]
51+
fn test_examples() {
52+
assert_eq!(
53+
solve(
54+
r#"5,4
55+
4,2
56+
4,5
57+
3,0
58+
2,1
59+
6,3
60+
2,4
61+
1,5
62+
0,6
63+
3,3
64+
2,6
65+
5,1
66+
1,2
67+
5,5
68+
2,5
69+
6,5
70+
1,4
71+
0,4
72+
6,4
73+
1,1
74+
6,1
75+
1,0
76+
0,5
77+
1,6
78+
2,0"#
79+
.into(),
80+
6,
81+
12
82+
)
83+
.into(),
84+
Solution::from((22, "6,1".to_string()))
85+
);
86+
}
87+
}

utils/src/graphs.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,22 @@ pub trait UnweightedGraph {
2020

2121
#[derive(Debug, Clone, PartialEq, Eq)]
2222
pub struct BfsResult<N: Node> {
23-
distance: Option<usize>,
24-
visited: HashSet<N>,
23+
pub distance: Option<usize>,
24+
pub visited: HashSet<N>,
2525
}
2626

2727
pub fn bfs<N: Node>(
2828
graph: &impl UnweightedGraph<Node = N>,
2929
start: impl Into<N>,
30-
end: impl Into<N>) -> BfsResult<N> {
30+
end: impl Into<N>,
31+
) -> BfsResult<N> {
3132
bfs_impl(graph, start, Some(end.into()))
3233
}
3334

34-
3535
pub fn floodfill<N: Node>(
3636
graph: &impl UnweightedGraph<Node = N>,
37-
start: impl Into<N>) -> HashSet<N> {
37+
start: impl Into<N>,
38+
) -> HashSet<N> {
3839
bfs_impl(graph, start, None).visited
3940
}
4041

utils/src/input.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use itertools::Itertools;
44

55
use crate::{grid::Grid, math::Vec2D, sparse_grid::SparseGrid};
66

7+
#[derive(Debug, Clone)]
78
pub struct Input {
89
pub raw: String,
910
}
@@ -31,7 +32,7 @@ impl Input {
3132
self.raw.len()
3233
}
3334

34-
pub fn lines(&self) -> impl Iterator<Item = &str> + '_ {
35+
pub fn lines(&self) -> impl Iterator<Item = &str> + Clone + '_ {
3536
self.raw.lines()
3637
}
3738

0 commit comments

Comments
 (0)