Skip to content

Commit bfb9eb6

Browse files
author
Krystian Kaniowski
committed
aoc-2024 - Day 15 - part 1
1 parent cce54c7 commit bfb9eb6

File tree

4 files changed

+99
-21
lines changed

4 files changed

+99
-21
lines changed

advent-of-code-2024/src/Day10.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ fun main() {
4141

4242
val array = Array2d.readNumbers(input)
4343

44-
return array.getPositions(9)
44+
return array.findAll { it == 9 }
4545
.sumOf {
4646
goDown(array, listOf(it), 9, it.x, it.y)
4747
.filterNotNull()
@@ -55,7 +55,7 @@ fun main() {
5555

5656
val array = Array2d.readNumbers(input)
5757

58-
return array.getPositions(0)
58+
return array.findAll { it == 0 }
5959
.sumOf {
6060
goUp(array, listOf(it), 0, it.x, it.y)
6161
.filterNotNull()

advent-of-code-2024/src/Day15.kt

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import util.Array2d
2+
import util.Vector
3+
4+
// https://adventofcode.com/2024/day/15
5+
fun main() {
6+
7+
val INSTRUTCION_MAPPING = mapOf(
8+
'>' to Vector.RIGHT,
9+
'<' to Vector.LEFT,
10+
'^' to Vector.UP,
11+
'v' to Vector.DOWN,
12+
)
13+
14+
val WALL = '#'
15+
val EMPTY = '.'
16+
val MACHINE = '@'
17+
val BOX = 'O'
18+
val BOX_2_LEFT = '['
19+
val BOX_2_RIGHT = ']'
20+
21+
fun Vector.isVertical() = this in listOf(Vector.UP, Vector.DOWN)
22+
23+
fun part1(input: List<String>): Int {
24+
25+
val map = Array2d.readChar(input.filter { it.contains(WALL) })
26+
val instructions = input.filter { it.any { it in INSTRUTCION_MAPPING.keys } }
27+
.flatMap { it.toList() }
28+
.mapNotNull { INSTRUTCION_MAPPING[it] }
29+
30+
var position = map.findAny { it == MACHINE }!!
31+
32+
instructions.forEach { vector ->
33+
var head = position
34+
val snake = mutableListOf(head)
35+
while (map[head + vector] == BOX) {
36+
head += vector
37+
snake.add(head)
38+
}
39+
if (map[head + vector] == EMPTY) {
40+
snake.reversed().forEachIndexed { index, point ->
41+
map[point + vector] = map[point]
42+
if (index == snake.size - 1) {
43+
position = point + vector
44+
map[point] = EMPTY
45+
}
46+
}
47+
}
48+
}
49+
50+
val boxes = map.findAll { it == BOX }
51+
52+
return boxes.sumOf { 100 * it.y + it.x }
53+
}
54+
55+
fun part2(input: List<String>): Int {
56+
return TODO()
57+
}
58+
59+
val testInput = readInput("Day15_test")
60+
val input = readInput("Day15")
61+
62+
test(10092) { part1(testInput) }
63+
exec { part1(input) }
64+
test(9021) { part2(testInput) }
65+
exec { part2(input) }
66+
}

advent-of-code-2024/src/util/Array2d.kt

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,53 +8,64 @@ class Array2d<Type>(
88

99
private val array: MutableList<MutableList<Type>> = MutableList(height) { MutableList(width) { defaultValue } }
1010

11+
operator fun get(point: Point) = get(point.x, point.y)
1112
operator fun get(x: Int, y: Int): Type = array[y][x]
13+
14+
fun getSafe(point: Point) = getSafe(point.x, point.y)
15+
fun getSafe(x: Int, y: Int) = if (isInBounds(x, y)) array[y][x] else null
16+
17+
operator fun set(point: Point, value: Type) = set(point.x, point.y, value)
1218
operator fun set(x: Int, y: Int, value: Type) {
1319
array[y][x] = value
1420
}
1521

16-
operator fun set(point: Point, value: Type) = set(point.x, point.y, value)
17-
18-
operator fun get(point: Point) = get(point.x, point.y)
19-
2022
fun setSafe(point: Point, value: Type) = setSafe(point.x, point.y, value)
2123
fun setSafe(x: Int, y: Int, value: Type) {
2224
if (isInBounds(x, y)) array[y][x] = value
2325
}
2426

25-
fun getSafe(point: Point) = getSafe(point.x, point.y)
26-
fun getSafe(x: Int, y: Int) = if (isInBounds(x, y)) array[y][x] else null
27+
fun isInBounds(point: Point) = isInBounds(point.x, point.y)
28+
fun isInBounds(x: Int, y: Int) = x in 0 until width && y in 0 until height
2729

28-
fun forEach(action: (x: Int, y: Int, value: Type) -> Unit) {
30+
fun findAny(filter: (Type) -> Boolean): Point? {
2931
for (y in array.indices) {
3032
for (x in array[y].indices) {
31-
action(x, y, array[y][x])
33+
if (filter(array[y][x])) return Point(x, y)
3234
}
3335
}
36+
return null
3437
}
3538

36-
fun getPositions(value: Type): List<Point> {
37-
return array.mapIndexed { y, list -> list.mapIndexed { x, v -> if (v == value) Point(x, y) else null } }
38-
.flatten()
39-
.filterNotNull()
39+
fun findAll(filter: (Type) -> Boolean): List<Point> {
40+
val findings = mutableListOf<Point>()
41+
for (y in array.indices) {
42+
for (x in array[y].indices) {
43+
if (filter(array[y][x])) findings.add(Point(x, y))
44+
}
45+
}
46+
return findings
4047
}
4148

42-
fun isInBounds(point: Point) = isInBounds(point.x, point.y)
49+
fun forEach(action: (x: Int, y: Int, value: Type) -> Unit) {
50+
for (y in array.indices) {
51+
for (x in array[y].indices) {
52+
action(x, y, array[y][x])
53+
}
54+
}
55+
}
4356

44-
fun isInBounds(x: Int, y: Int) = x in 0 until width && y in 0 until height
57+
fun count(filter: (Type) -> Boolean): Int = array.sumOf { it.count { filter(it) } }
4558

4659
fun createMask(): Array2d<Boolean> = Array2d(width, height, false)
4760

48-
fun count(filter: (Type) -> Boolean): Int = array.sumOf { it.count { filter(it) } }
49-
5061
fun print(mapper: (Type) -> Char) {
5162
for (y in array.indices) {
5263
for (x in array[y].indices) {
53-
print(mapper(array[x][y]))
64+
print(mapper(array[y][x]))
5465
}
55-
println("")
66+
println()
5667
}
57-
println("")
68+
println()
5869
}
5970

6071
companion object {

advent-of-code-2024/src/util/Point.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package util
33
data class Point(val x: Int, val y: Int) {
44

55
operator fun plus(vector: Vector) = Point(x + vector.x, y + vector.y)
6+
operator fun minus(vector: Vector) = Point(x - vector.x, y - vector.y)
67

78
override fun toString(): String {
89
return "[$x, $y]"

0 commit comments

Comments
 (0)