Skip to content

Commit c645db7

Browse files
authored
Day 08 2024 (#267)
1 parent b8d2f75 commit c645db7

File tree

4 files changed

+126
-0
lines changed

4 files changed

+126
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package me.peckb.aoc._2024.calendar.day08
2+
3+
import me.peckb.aoc.generators.CombinationsGenerator
4+
import javax.inject.Inject
5+
import me.peckb.aoc.generators.InputGenerator.InputGeneratorFactory
6+
7+
class Day08 @Inject constructor(
8+
private val generatorFactory: InputGeneratorFactory,
9+
) {
10+
fun partOne(filename: String) = generatorFactory.forFile(filename).read { lines ->
11+
val (maxY, maxX, antenna) = findAntenna(lines)
12+
val antinodes = findAntinodes(maxY, maxX, antenna, false)
13+
14+
antinodes.size
15+
}
16+
17+
fun partTwo(filename: String) = generatorFactory.forFile(filename).read { lines ->
18+
val (maxY, maxX, antenna) = findAntenna(lines)
19+
val antinodes = findAntinodes(maxY, maxX, antenna, true)
20+
21+
antinodes.plus(
22+
antenna.values.flatMap { it.toList() }
23+
).size
24+
}
25+
26+
private fun findAntenna(input: Sequence<String>): AntennaData {
27+
val antenna = mutableMapOf<Char, Array<Location>>()
28+
29+
var maxY = 0
30+
var maxX = 0
31+
32+
input.forEachIndexed { yIndex, line ->
33+
maxY = maxOf(maxY, yIndex)
34+
line.forEachIndexed { xIndex, space ->
35+
maxX = maxOf(maxX, xIndex)
36+
when (space) {
37+
'.' -> { /* skip */ }
38+
else -> antenna.merge(space, arrayOf(Location(yIndex, xIndex))) { a, b -> a + b }
39+
}
40+
}
41+
}
42+
43+
return AntennaData(maxY, maxX, antenna)
44+
}
45+
46+
private fun findAntinodes(
47+
maxY: Int,
48+
maxX: Int,
49+
antenna: Map<Char, Array<Location>>,
50+
forever: Boolean
51+
): Set<Location> {
52+
val antinodes = mutableSetOf<Location>()
53+
54+
fun find(antenna: Location, xDelta: Int, yDelta: Int, mover: (Int, Int) -> Int) {
55+
var inbounds = forever
56+
var frequency = 1
57+
58+
val (y, x) = antenna
59+
60+
do {
61+
val possibleY = mover(y, (yDelta * frequency))
62+
val possibleX = mover(x, (xDelta * frequency))
63+
64+
if (possibleX in 0..maxX && possibleY in 0..maxY) {
65+
antinodes.add(Location(possibleY, possibleX))
66+
frequency++
67+
} else {
68+
inbounds = false
69+
}
70+
} while (inbounds)
71+
}
72+
73+
antenna.forEach { (_, locations) ->
74+
val combinations = CombinationsGenerator.findCombinations(locations, 2)
75+
76+
combinations.forEach { (a, b) ->
77+
val xDelta = a.x - b.x
78+
val yDelta = a.y - b.y
79+
80+
find(a, xDelta, yDelta, Int::plus)
81+
find(b, xDelta, yDelta, Int::minus)
82+
}
83+
}
84+
85+
return antinodes
86+
}
87+
}
88+
89+
data class AntennaData(val maxY: Int, val maxX: Int, val locations: Map<Char, Array<Location>>)
90+
91+
data class Location(val y: Int, val x: Int)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
## [Day 8: Resonant Collinearity](https://adventofcode.com/2024/day/8)

src/test/kotlin/me/peckb/aoc/_2024/TestDayComponent.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import me.peckb.aoc._2024.calendar.day04.Day04Test
77
import me.peckb.aoc._2024.calendar.day05.Day05Test
88
import me.peckb.aoc._2024.calendar.day06.Day06Test
99
import me.peckb.aoc._2024.calendar.day07.Day07Test
10+
import me.peckb.aoc._2024.calendar.day08.Day08Test
1011
import javax.inject.Singleton
1112
import me.peckb.aoc.DayComponent
1213
import me.peckb.aoc.InputModule
@@ -22,4 +23,5 @@ internal interface TestDayComponent : DayComponent {
2223
fun inject(day05Test: Day05Test)
2324
fun inject(day06Test: Day06Test)
2425
fun inject(day07Test: Day07Test)
26+
fun inject(day08Test: Day08Test)
2527
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package me.peckb.aoc._2024.calendar.day08
2+
3+
import javax.inject.Inject
4+
5+
import me.peckb.aoc._2024.DaggerTestDayComponent
6+
import org.junit.jupiter.api.Assertions.assertEquals
7+
import org.junit.jupiter.api.BeforeEach
8+
import org.junit.jupiter.api.Test
9+
10+
internal class Day08Test {
11+
@Inject
12+
lateinit var day08: Day08
13+
14+
@BeforeEach
15+
fun setup() {
16+
DaggerTestDayComponent.create().inject(this)
17+
}
18+
19+
@Test
20+
fun testDay08PartOne() {
21+
assertEquals(369, day08.partOne(DAY_08))
22+
}
23+
24+
@Test
25+
fun testDay08PartTwo() {
26+
assertEquals(1169, day08.partTwo(DAY_08))
27+
}
28+
29+
companion object {
30+
private const val DAY_08: String = "advent-of-code-input/2024/day08.input"
31+
}
32+
}

0 commit comments

Comments
 (0)