Skip to content

Commit 118883c

Browse files
authored
Day 14 2024 (#274)
1 parent 5eecbb6 commit 118883c

File tree

5 files changed

+245
-0
lines changed

5 files changed

+245
-0
lines changed
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package me.peckb.aoc._2024.calendar.day14
2+
3+
import arrow.core.Tuple4
4+
import javax.inject.Inject
5+
import me.peckb.aoc.generators.InputGenerator.InputGeneratorFactory
6+
import java.io.File
7+
import kotlin.math.sign
8+
9+
class Day14 @Inject constructor(
10+
private val generatorFactory: InputGeneratorFactory,
11+
) {
12+
fun partOne(filename: String) = generatorFactory.forFile(filename).readAs(::day14) { input ->
13+
val timeToElapse = 100L
14+
// note data is [X, Y] format!
15+
// The robots outside the actual bathroom are in a space which is 101 tiles wide and 103 tiles tall
16+
val robotLocations = input.map { r ->
17+
var robotXAfter = (r.posX + (r.velX * timeToElapse)) % SPACE_WIDTH
18+
var robotYAfter = (r.posY + (r.velY * timeToElapse)) % SPACE_HEIGHT
19+
20+
if (robotXAfter.sign < 0) robotXAfter += SPACE_WIDTH
21+
if (robotYAfter.sign < 0) robotYAfter += SPACE_HEIGHT
22+
23+
robotXAfter to robotYAfter
24+
}.toList()
25+
26+
val robotsByQuadrant = robotLocations.groupBy { robotLocation ->
27+
if (robotLocation.first < SPACE_WIDTH/2) {
28+
if (robotLocation.second < SPACE_HEIGHT/2) { 1 }
29+
else if (robotLocation.second > SPACE_HEIGHT/2) { 3 }
30+
else { 0 }
31+
} else if (robotLocation.first > SPACE_WIDTH/2) {
32+
if (robotLocation.second < SPACE_HEIGHT/2) { 2 }
33+
else if (robotLocation.second > SPACE_HEIGHT/2) { 4 }
34+
else { 0 }
35+
} else { 0 }
36+
}
37+
38+
robotsByQuadrant.entries.fold(1L) { acc, entry ->
39+
if (entry.key != 0) {
40+
acc * entry.value.size
41+
} else {
42+
acc
43+
}
44+
}
45+
}
46+
47+
fun partTwo(filename: String) = generatorFactory.forFile(filename).readAs(::day14) { input ->
48+
val space = Array(SPACE_HEIGHT) { Array(SPACE_WIDTH) { 0 } }
49+
val robots = input.toList()
50+
robots.forEach { space[it.posY][it.posX]++ }
51+
52+
var counter = 0
53+
loop@ while(counter < 10_000) {
54+
counter++
55+
robots.forEach { robot ->
56+
space[robot.posY][robot.posX]--
57+
var newX = robot.posX + robot.velX
58+
var newY = robot.posY + robot.velY
59+
60+
if (newX < 0) { newX += SPACE_WIDTH }
61+
else if (newX >= SPACE_WIDTH) { newX -= SPACE_WIDTH }
62+
63+
if (newY < 0) { newY += SPACE_HEIGHT }
64+
else if (newY >= SPACE_HEIGHT) { newY -= SPACE_HEIGHT }
65+
66+
robot.posX = newX
67+
robot.posY = newY
68+
space[robot.posY][robot.posX]++
69+
}
70+
71+
val foundTopBorder = space.withIndex().all { (index, row) ->
72+
val rowStr = row.map {
73+
when (it) {
74+
0 -> " "
75+
else -> "*"
76+
}
77+
}.joinToString("")
78+
79+
Tree.IMAGE[index] == rowStr
80+
}
81+
82+
if (foundTopBorder) break@loop
83+
}
84+
counter
85+
}
86+
87+
private fun day14(line: String): Robot {
88+
return line.split(" ")
89+
.map { it.drop(2).split(",") }
90+
.let { (pos, vel) -> pos.map { it.toInt() } to vel.map { it.toInt() } }
91+
.let { (pos, vel) -> Robot(pos[0], pos[1], vel[0], vel[1]) }
92+
}
93+
94+
companion object {
95+
private const val SPACE_WIDTH = 101
96+
private const val SPACE_HEIGHT = 103
97+
}
98+
}
99+
100+
data class Robot(var posX: Int, var posY: Int, val velX: Int, val velY: Int)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
## [Day 14: Restroom Redoubt](https://adventofcode.com/2024/day/14)
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package me.peckb.aoc._2024.calendar.day14
2+
3+
// NOTE: to find my tree - I spit out 10k word of areas into a file
4+
// opened the file and scanned until something jumped out at me.
5+
object Tree {
6+
val IMAGE =
7+
""" *
8+
* * * *
9+
*
10+
11+
* * *
12+
* *
13+
* *
14+
* *
15+
* *
16+
* * *
17+
*
18+
*
19+
* ** *
20+
*
21+
* *
22+
* * *
23+
*
24+
* *
25+
* *
26+
*
27+
******************************* *
28+
* *
29+
* * * * *
30+
* * * *
31+
* * * * *
32+
* * * * *
33+
* *** *
34+
* ***** *
35+
* ******* *
36+
* ********* *
37+
* * ***** *
38+
* * ******* *
39+
* ********* *
40+
* *********** *
41+
* ************* *
42+
* * * ********* * *
43+
* *********** *
44+
* * ************* *
45+
* *************** *
46+
* ***************** *
47+
* * * ************* * *
48+
* * * *************** *
49+
* ***************** * *
50+
* ******************* *
51+
* ********************* * *
52+
* *** *
53+
* *** * *
54+
* *** * *
55+
* * *
56+
* *
57+
* * *
58+
* *
59+
******************************* * *
60+
*
61+
* *
62+
* * * * *
63+
* * *
64+
65+
66+
67+
* *
68+
* * *
69+
* * * *
70+
* *
71+
*
72+
* *
73+
*
74+
* *
75+
* *
76+
77+
*
78+
* *
79+
80+
* *
81+
82+
* *
83+
* * *
84+
85+
* * *
86+
*
87+
*
88+
*
89+
* * *
90+
91+
* *
92+
93+
*
94+
* *
95+
* * *
96+
* * * *
97+
*
98+
*
99+
* * *
100+
*
101+
*
102+
*
103+
104+
* *
105+
106+
*
107+
* *
108+
* *
109+
* * * """.split("\n")
110+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import me.peckb.aoc._2024.calendar.day10.Day10Test
1313
import me.peckb.aoc._2024.calendar.day11.Day11Test
1414
import me.peckb.aoc._2024.calendar.day12.Day12Test
1515
import me.peckb.aoc._2024.calendar.day13.Day13Test
16+
import me.peckb.aoc._2024.calendar.day14.Day14Test
1617
import javax.inject.Singleton
1718
import me.peckb.aoc.DayComponent
1819
import me.peckb.aoc.InputModule
@@ -34,4 +35,5 @@ internal interface TestDayComponent : DayComponent {
3435
fun inject(day11Test: Day11Test)
3536
fun inject(day12Test: Day12Test)
3637
fun inject(day13Test: Day13Test)
38+
fun inject(day14Test: Day14Test)
3739
}
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.day14
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 Day14Test {
11+
@Inject
12+
lateinit var day14: Day14
13+
14+
@BeforeEach
15+
fun setup() {
16+
DaggerTestDayComponent.create().inject(this)
17+
}
18+
19+
@Test
20+
fun testDay14PartOne() {
21+
assertEquals(229980828, day14.partOne(DAY_14))
22+
}
23+
24+
@Test
25+
fun testDay14PartTwo() {
26+
assertEquals(7132, day14.partTwo(DAY_14))
27+
}
28+
29+
companion object {
30+
private const val DAY_14: String = "advent-of-code-input/2024/day14.input"
31+
}
32+
}

0 commit comments

Comments
 (0)