Skip to content

Commit ba805ff

Browse files
committed
Day 8 part 2
1 parent e82fac2 commit ba805ff

File tree

3 files changed

+76
-18
lines changed

3 files changed

+76
-18
lines changed

src/adventofcode2024.gleam

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ fn run(d: Int) -> Nil {
5151
5 -> day5.part2(input) |> int.to_string
5252
6 -> day6.part2(input) |> int.to_string
5353
7 -> day7.part2(input) |> int.to_string
54+
8 -> day8.part2(input) |> int.to_string
5455
_ -> "(not implemented)"
5556
}
5657
})

src/day8.gleam

+58-18
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,35 @@ import grid.{type Pos}
66
import parse
77

88
pub fn part1(input: String) -> Int {
9-
let #(antennas, width, height) = parse_input(input)
9+
let #(map, in_bounds) = parse_input(input)
1010

11-
antennas
12-
|> dict.keys
13-
|> list.flat_map(fn(label) { antinodes_for(antennas, label, width, height) })
11+
map
12+
|> dict.values
13+
|> list.flat_map(fn(antennas) { antinodes_for(antennas, in_bounds) })
1414
|> list.unique
1515
|> list.length
1616
}
1717

18-
fn antinodes_for(
19-
antennas: Dict(String, List(Pos)),
20-
label: String,
21-
width: Int,
22-
height: Int,
23-
) -> List(Pos) {
18+
pub fn part2(input: String) -> Int {
19+
let #(map, in_bounds) = parse_input(input)
20+
21+
map
22+
|> dict.values
23+
|> list.flat_map(fn(antennas) { harmonic_antinodes_for(antennas, in_bounds) })
24+
|> list.unique
25+
|> list.length
26+
}
27+
28+
type BoundFn =
29+
fn(Pos) -> Bool
30+
31+
fn antinodes_for(antennas: List(Pos), in_bounds: BoundFn) -> List(Pos) {
2432
antennas
25-
|> dict.get(label)
26-
|> result.unwrap([])
2733
|> list.combination_pairs
2834
|> list.flat_map(fn(pair) {
2935
[individual_antinode(pair.0, pair.1), individual_antinode(pair.1, pair.0)]
3036
})
31-
|> list.filter(fn(pos) {
32-
pos.0 >= 0 && pos.0 < width && pos.1 >= 0 && pos.1 < height
33-
})
37+
|> list.filter(in_bounds)
3438
}
3539

3640
fn individual_antinode(a: Pos, b: Pos) -> Pos {
@@ -39,7 +43,40 @@ fn individual_antinode(a: Pos, b: Pos) -> Pos {
3943
#(a.0 + dx, a.1 + dy)
4044
}
4145

42-
fn parse_input(input: String) -> #(Dict(String, List(Pos)), Int, Int) {
46+
fn harmonic_antinodes_for(antennas: List(Pos), in_bounds: BoundFn) -> List(Pos) {
47+
antennas
48+
|> list.combination_pairs
49+
|> list.flat_map(fn(pair) {
50+
[
51+
find_harmonic_antinodes(pair.0, pair.1, in_bounds),
52+
find_harmonic_antinodes(pair.1, pair.0, in_bounds),
53+
]
54+
})
55+
|> list.flatten
56+
}
57+
58+
fn find_harmonic_antinodes(a: Pos, b: Pos, in_bounds: BoundFn) -> List(Pos) {
59+
let dx = a.0 - b.0
60+
let dy = a.1 - b.1
61+
62+
next_harmonic_antinode(a, dx, dy, in_bounds, [a])
63+
}
64+
65+
fn next_harmonic_antinode(
66+
a: Pos,
67+
dx: Int,
68+
dy: Int,
69+
in_bounds: BoundFn,
70+
nodes: List(Pos),
71+
) -> List(Pos) {
72+
let node = #(a.0 + dx, a.1 + dy)
73+
case in_bounds(node) {
74+
True -> next_harmonic_antinode(node, dx, dy, in_bounds, [node, ..nodes])
75+
False -> nodes
76+
}
77+
}
78+
79+
fn parse_input(input: String) -> #(Dict(String, List(Pos)), BoundFn) {
4380
let lines = parse.lines(input)
4481

4582
let pos_to_char =
@@ -56,6 +93,10 @@ fn parse_input(input: String) -> #(Dict(String, List(Pos)), Int, Int) {
5693
let width = lines |> list.first |> result.unwrap("") |> string.length
5794
let height = lines |> list.length
5895

96+
let in_bounds = fn(p: Pos) {
97+
p.0 >= 0 && p.0 < width && p.1 >= 0 && p.1 < height
98+
}
99+
59100
#(
60101
pos_to_char
61102
|> dict.values
@@ -74,7 +115,6 @@ fn parse_input(input: String) -> #(Dict(String, List(Pos)), Int, Int) {
74115
)
75116
})
76117
|> dict.from_list,
77-
width,
78-
height,
118+
in_bounds,
79119
)
80120
}

test/day8_test.gleam

+17
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,23 @@ const example1 = "............
2121
............
2222
"
2323

24+
const example2 = "T.........
25+
...T......
26+
.T........
27+
..........
28+
..........
29+
..........
30+
..........
31+
..........
32+
..........
33+
..........
34+
"
35+
2436
pub fn part1_test() {
2537
day8.part1(example1) |> should.equal(14)
2638
}
39+
40+
pub fn part2_test() {
41+
day8.part2(example1) |> should.equal(34)
42+
day8.part2(example2) |> should.equal(9)
43+
}

0 commit comments

Comments
 (0)