Skip to content

Commit b2b6376

Browse files
committed
Day 10 solutions
1 parent 4229737 commit b2b6376

File tree

5 files changed

+218
-3
lines changed

5 files changed

+218
-3
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,4 @@ This should start the server at `localhost:8080`.
9595
❄️ [Day 07](aoc-solver/src/y2024/day07.rs)
9696
❄️ [Day 08](aoc-solver/src/y2024/day08.rs)
9797
❄️ [Day 09](aoc-solver/src/y2024/day09.rs)
98+
❄️ [Day 10](aoc-solver/src/y2024/day10.rs)

aoc-solver/src/y2024/day10.rs

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
use std::collections::HashMap;
2+
3+
use itertools::Itertools;
4+
5+
use crate::solution::{AocError, Solution};
6+
7+
type Grid = Vec<Vec<u32>>;
8+
9+
struct Search {
10+
elevation: u32,
11+
coords: (usize, usize),
12+
}
13+
14+
const DIRECTIONS: [(isize, isize); 4] = [(0, -1), (1, 0), (0, 1), (-1, 0)];
15+
16+
fn parse(input: &str) -> Result<Grid, AocError> {
17+
let area = input
18+
.trim()
19+
.lines()
20+
.map(|line| {
21+
line.trim()
22+
.chars()
23+
.map(|c| {
24+
c.to_digit(10)
25+
.ok_or_else(|| AocError::parse(c.to_string(), "Unexpected character"))
26+
})
27+
.collect()
28+
})
29+
.try_collect()?;
30+
31+
Ok(area)
32+
}
33+
34+
fn is_within_bounds(x: isize, y: isize, width: isize, height: isize) -> bool {
35+
x >= 0 && y >= 0 && x < width && y < height
36+
}
37+
38+
fn search_trails((x, y): (usize, usize), grid: &[Vec<u32>]) -> HashMap<(usize, usize), usize> {
39+
let mut stack: Vec<Search> = Vec::new();
40+
41+
let width = grid[0].len() as isize;
42+
let height = grid.len() as isize;
43+
44+
stack.push(Search {
45+
elevation: grid[y][x],
46+
coords: (x, y),
47+
});
48+
49+
let mut trails: HashMap<(usize, usize), usize> = HashMap::new();
50+
51+
while let Some(Search { coords, elevation }) = stack.pop() {
52+
if elevation == 9 {
53+
*trails.entry(coords).or_insert(0) += 1;
54+
continue;
55+
}
56+
57+
for (dx, dy) in DIRECTIONS {
58+
let next: (isize, isize) = (coords.0 as isize + dx, coords.1 as isize + dy);
59+
60+
if is_within_bounds(next.0, next.1, width, height) {
61+
let next_elevation = grid[next.1 as usize][next.0 as usize];
62+
63+
if next_elevation.saturating_sub(elevation) != 1 {
64+
// Trail should always increase by a height of exactly 1 at each step
65+
continue;
66+
}
67+
68+
stack.push(Search {
69+
elevation: next_elevation,
70+
coords: (next.0 as usize, next.1 as usize),
71+
});
72+
}
73+
}
74+
}
75+
76+
trails
77+
}
78+
79+
pub struct Day10;
80+
impl Solution for Day10 {
81+
type A = usize;
82+
type B = usize;
83+
84+
fn default_input(&self) -> &'static str {
85+
include_str!("../../../inputs/2024/day10.txt")
86+
}
87+
88+
fn part_1(&self, input: &str) -> Result<usize, AocError> {
89+
let grid = parse(input)?;
90+
let mut score = 0;
91+
92+
for y in 0..grid.len() {
93+
for x in 0..grid[y].len() {
94+
if grid[y][x] == 0 {
95+
let peaks = search_trails((x, y), &grid);
96+
score += peaks.len()
97+
}
98+
}
99+
}
100+
101+
Ok(score)
102+
}
103+
104+
fn part_2(&self, input: &str) -> Result<usize, AocError> {
105+
let grid = parse(input)?;
106+
let mut score = 0;
107+
108+
for y in 0..grid.len() {
109+
for x in 0..grid[y].len() {
110+
if grid[y][x] == 0 {
111+
let peaks = search_trails((x, y), &grid);
112+
let trails: usize = peaks.values().sum();
113+
score += trails
114+
}
115+
}
116+
}
117+
118+
Ok(score)
119+
}
120+
}
121+
122+
#[cfg(test)]
123+
mod tests {
124+
use super::*;
125+
126+
#[test]
127+
fn it_solves_part1_example_1() {
128+
assert_eq!(
129+
Day10.part_1(
130+
"89010123\n\
131+
78121874\n\
132+
87430965\n\
133+
96549874\n\
134+
45678903\n\
135+
32019012\n\
136+
01329801\n\
137+
10456732"
138+
),
139+
Ok(36)
140+
);
141+
}
142+
143+
#[test]
144+
fn it_solves_part1_example_2() {
145+
assert_eq!(
146+
Day10.part_2(
147+
"89010123\n\
148+
78121874\n\
149+
87430965\n\
150+
96549874\n\
151+
45678903\n\
152+
32019012\n\
153+
01329801\n\
154+
10456732"
155+
),
156+
Ok(81)
157+
);
158+
}
159+
}

aoc-solver/src/y2024/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub mod day06;
99
pub mod day07;
1010
pub mod day08;
1111
pub mod day09;
12-
// pub mod day10;
12+
pub mod day10;
1313
// pub mod day11;
1414
// pub mod day12;
1515
// pub mod day13;
@@ -26,7 +26,7 @@ pub mod day09;
2626
// pub mod day24;
2727
// pub mod day25;
2828

29-
pub const MAX_DAYS: u8 = 9;
29+
pub const MAX_DAYS: u8 = 10;
3030

3131
pub struct Y2024;
3232

@@ -42,7 +42,7 @@ impl Solver for Y2024 {
4242
7 => day07::Day07.run(input, 7, 2024),
4343
8 => day08::Day08.run(input, 8, 2024),
4444
9 => day09::Day09.run(input, 9, 2024),
45-
// 10 => day10::Day10.run(input, 10, 2024),
45+
10 => day10::Day10.run(input, 10, 2024),
4646
// 11 => day11::Day11.run(input, 11, 2024),
4747
// 12 => day12::Day12.run(input, 12, 2024),
4848
// 13 => day13::Day13.run(input, 13, 2024),

aoc-web/src/header.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub fn header(props: &HeaderProps) -> Html {
2828
<NavLink route={Route::Solution { year: 2024, day: 7 }} current={props.route.clone()} text={"7"}/>
2929
<NavLink route={Route::Solution { year: 2024, day: 8 }} current={props.route.clone()} text={"8"}/>
3030
<NavLink route={Route::Solution { year: 2024, day: 9 }} current={props.route.clone()} text={"9"}/>
31+
<NavLink route={Route::Solution { year: 2024, day: 10 }} current={props.route.clone()} text={"10"}/>
3132
</>
3233
}
3334
},

inputs/2024/day10.txt

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
034565433432321821235456556798712438943432345432101010
2+
125674344341210930012367349897601123876501656543238923
3+
545981265210523841112398232098532014101665437654147014
4+
436780378019654756501454101123442125012878328956056985
5+
521091489328765661498760130210356916763969012347841076
6+
342698456410644570187321221202197809854054521078932987
7+
434784387569653089298435430143087612870123654169410673
8+
525601295678762120387589347834561543965434783254321034
9+
510567856789854871456678956921670123457650199165890321
10+
654356943889903962345665067830589894398743278056785410
11+
701245012958712653434784167845678765210634565410156789
12+
898434321867012344321093254976104543231023876321943089
13+
686321780154102101287765323987267650122012989423872176
14+
567980691233283237898894015416398532143606788714565765
15+
408974500543098946907623234505458545014545698601159854
16+
312363217632127655416510107612369876105894332589018345
17+
221457898565634562323421458733478983276701201478121230
18+
100656967874567641032102369021098744589856782363210121
19+
789345450923498634543001078112321654678345891054308701
20+
654212321012654521694210981205430903543232654143489610
21+
503403430156787610784300870376567812654121743267876523
22+
012567567343898525695421889487854925780010893210965432
23+
123498788210123436786438976598943056891234984921014101
24+
019567699101898345877567887678762147878765675870123012
25+
108754543210567212968900194589054038969454566767636323
26+
205610121056750303453213293032123229454323879098545438
27+
014981232347841219874984782143210110301012978121654569
28+
123672654338932306705675676154560121212307665430743478
29+
298543789221069455012310145069430430925408578989832387
30+
567010176109178764563498232178521567876519454567601296
31+
432123485458769853074567310123678106898323343218970345
32+
012034394367458102189601489433439256765401252102181234
33+
123465210210343012078732676512508349850106769843098321
34+
054896990101212043896543216109612556743219856784587410
35+
969887889654302158987894107898743445654340145697656531
36+
878791078745983467856765545677654354567854234548545621
37+
745622363215676500345653231987980123498960129639343210
38+
034215454301876211256570120345678154323870038721658343
39+
122100189321945308967981011234569067212721801290569012
40+
543893276430932457898876323233432178008934980387378143
41+
456764345567801966501895400145567889127645673456269654
42+
369632105478765873432689312176876901234560012562158765
43+
278543254309894569546576543089985432321071239873043210
44+
103450569212723278637434010034394321810980548954560127
45+
894321078112010198728922121165223010901289687643073438
46+
765697151003434587017213033278112987874398796542189569
47+
056788769876524326501304544569001056965834321233675678
48+
145679458985015415432987693432102345216945610344569547
49+
230989347034376102341056780540989104307898700123678632
50+
321078234123289211652346791691071234487465410878766781
51+
989165106000105690789905882782360943296578321969215690
52+
076234245612234782349814943485456850123489100154304385
53+
145210238763145671456723876596306765012101256701235276
54+
234300149854078980365432101487217898721032349810120123

0 commit comments

Comments
 (0)