1+ import de.ronny_h.extensions.Coordinates
2+ import de.ronny_h.extensions.Direction
3+ import de.ronny_h.extensions.Grid
4+
5+ fun main () {
6+ val day = " Day15"
7+
8+ println (" $day part 1" )
9+
10+ fun part1 (input : List <String >): Int {
11+ val warehouse = Warehouse (input.takeWhile { it.isNotBlank() })
12+ warehouse.printGrid()
13+
14+ val movements = input
15+ .takeLastWhile { it.isNotBlank() }
16+ .joinToString(separator = " " )
17+ .map {
18+ when (it) {
19+ ' ^' -> Direction .NORTH
20+ ' >' -> Direction .EAST
21+ ' v' -> Direction .SOUTH
22+ ' <' -> Direction .WEST
23+ else -> error(" Unexpected direction Char: $it " )
24+ }
25+ }
26+
27+ warehouse.moveRobot(movements)
28+ warehouse.printGrid()
29+
30+ return warehouse.sumGPSCoordinates()
31+ }
32+
33+ printAndCheck(
34+ """
35+ ########
36+ #..O.O.#
37+ ##@.O..#
38+ #...O..#
39+ #.#.O..#
40+ #...O..#
41+ #......#
42+ ########
43+
44+ <^^>>>vv<v>>v<<
45+ """ .trimIndent().lines(),
46+ ::part1, 2028
47+ )
48+
49+ val testInput = readInput(" ${day} _test" )
50+ printAndCheck(testInput, ::part1, 10092 )
51+
52+ val input = readInput(day)
53+ printAndCheck(input, ::part1, 1463715 )
54+ }
55+
56+ private class Warehouse (input : List <String >) : Grid<Char>(input) {
57+ private val wall = ' #'
58+ private val robot = ' @'
59+ private val free = ' .'
60+ private val goods = ' O'
61+
62+ override val nullElement = wall
63+ override fun Char.toElementType (): Char = this
64+
65+ fun moveRobot (movements : List <Direction >) {
66+ movements.fold(findTheRobot()) { position, direction ->
67+ if (tryToMove(position, direction, robot)) {
68+ position + direction
69+ } else {
70+ position
71+ }
72+ }
73+ }
74+
75+ private fun tryToMove (from : Coordinates , direction : Direction , thing : Char ): Boolean {
76+ val target = from + direction
77+ if (getAt(target) == free) {
78+ setAt(target, thing)
79+ setAt(from, free)
80+ return true
81+ }
82+ if (getAt(target) == wall) {
83+ return false
84+ }
85+ check(getAt(target) == goods)
86+ if (tryToMove(target, direction, goods)) {
87+ setAt(target, thing)
88+ setAt(from, free)
89+ return true
90+ }
91+ return false
92+ }
93+
94+ private fun findTheRobot (): Coordinates = forEachElement { row, col, element ->
95+ if (element == robot) Coordinates (row, col) else null
96+ }.filterNotNull().first()
97+
98+ fun sumGPSCoordinates (): Int = forEachElement { row, col, element ->
99+ if (element == goods) {
100+ 100 * row + col
101+ } else {
102+ 0
103+ }
104+ }.sum()
105+
106+ }
0 commit comments