@@ -5,66 +5,60 @@ import kotlin.math.abs
55
66val hallwayStops = listOf (0 , 1 , 3 , 5 , 7 , 9 , 10 )
77val doors = listOf (2 , 4 , 6 , 8 )
8- val room1 = listOf (11 , 12 )
9- val room2 = listOf (13 , 14 )
10- val room3 = listOf (15 , 16 )
11- val room4 = listOf (17 , 18 )
8+ val room1 = listOf (11 , 12 , 13 , 14 )
9+ val room2 = listOf (21 , 22 , 23 , 24 )
10+ val room3 = listOf (31 , 32 , 33 , 34 )
11+ val room4 = listOf (41 , 42 , 43 , 44 )
1212val rooms = listOf (room1, room2, room3, room4)
1313val costs = listOf (1 , 10 , 100 , 1000 )
1414
15- data class State (val positions : List <Int >) {
15+ data class State (val numNumbers : Int , val positions : List <Int >) {
1616
1717 fun isFinished (): Boolean {
18- return positions[0 ] in room1
19- && positions[1 ] in room1
20- && positions[2 ] in room2
21- && positions[3 ] in room2
22- && positions[4 ] in room3
23- && positions[5 ] in room3
24- && positions[6 ] in room4
25- && positions[7 ] in room4
18+ return positions.chunked(numNumbers).mapIndexed { i, poses ->
19+ poses.all { it in rooms[i] }
20+ }.all { it }
2621 }
2722
28- fun getPossibleMoves () : List <Pair <Int , State >> {
23+ fun getPossibleMoves (): List <Pair <Int , State >> {
2924 return positions.indices.flatMap { getMoves(it) }
3025 }
3126
32- private fun getMoves (amphi : Int ) : List <Pair <Int , State >> {
27+ private fun getMoves (amphi : Int ): List <Pair <Int , State >> {
3328 val pos = positions[amphi]
34- val goalRoom = amphi / 2
29+ val goalRoom = amphi / numNumbers
3530 val goalRoomSpots = rooms[goalRoom]
3631
3732 if (pos > 10 ) { // in a room
38- // don't make a move if in the correct spot
39- // if (pos in goalRoomSpots) {
40- // if (pos == goalRoomSpots[1]) { // In the back, ok
41- // return listOf()
42- // } else {
43- // // In the front, but the one behind is ok
44- // }
45- // }
46-
47-
48- val isInTheBack = pos % 2 == 0
49- if (isInTheBack) {
50- val isBlocked = positions.any { it == pos - 1 } // fix for 4
51- if (isBlocked) {
33+ if (pos in goalRoomSpots) { // don't make a move if in the correct spot
34+ // and nothing behind me that should out
35+ val range = (pos + 1 ).. ((goalRoom + 1 ) * 10 ) + numNumbers
36+ val blockedBehind = positions.filterIndexed { i, p -> p in range && i / numNumbers != goalRoom }
37+ if (blockedBehind.isEmpty()) {
5238 return listOf ()
5339 }
5440 }
5541
56- val currentRoom = (pos - 11 ) / 2
42+ val potentialBlockages = (pos - (pos % 10 ) + 1 ) until pos
43+ val isBlocked = positions.any { it in potentialBlockages }
44+ if (isBlocked) { // Can't move out
45+ return listOf ()
46+ }
47+
48+
49+ val currentRoom = (pos / 10 ) - 1
5750 val entrance = doors[currentRoom]
58- val stepToEntrance = if (isInTheBack) 2 else 1 // fix for 4
51+ val stepToEntrance = pos % 10
5952 val cost = costs[goalRoom]
6053
54+ // move to all possible hallway spots
6155 val moves = hallwayStops.mapNotNull { stop ->
62- if (canGoTo(to= stop, from= entrance)) {
56+ if (canGoTo(to = stop, from = entrance)) {
6357 val dst = abs(entrance - stop)
6458 val totalCost = cost * (stepToEntrance + dst)
6559 val newState = positions.toMutableList()
6660 newState[amphi] = stop
67- totalCost to State (newState)
61+ totalCost to State (numNumbers, newState)
6862 } else {
6963 null
7064 }
@@ -78,53 +72,74 @@ data class State(val positions: List<Int>) {
7872 }
7973
8074 val anyoneNotSupposedInTheRoom = positions.filterIndexed { i, amphiPos ->
81- amphiPos in goalRoomSpots && i / 2 != goalRoom // fix for 4
75+ amphiPos in goalRoomSpots && i / numNumbers != goalRoom
8276 }
83-
84- if (anyoneNotSupposedInTheRoom.any()) {
77+ if (anyoneNotSupposedInTheRoom.any()) { // Too early to go in
8578 return listOf ()
8679 }
8780
88- val otherIsThereAlready = positions.any {
89- it in goalRoomSpots
90- }
81+ val numAlreadyThere = positions.count { it in goalRoomSpots }
9182
92- val stepsFromEntrance = if (otherIsThereAlready) 1 else 2 // fix for 4
83+ val stepsFromEntrance = numNumbers - numAlreadyThere
9384 val stepsToEntrance = abs(pos - doorPos)
94- val finalPos = if (otherIsThereAlready) goalRoomSpots[0 ] else goalRoomSpots[ 1 ] // fix for 4
85+ val finalPos = goalRoomSpots[numNumbers - numAlreadyThere - 1 ]
9586 val cost = costs[goalRoom]
9687
9788 val totalCost = cost * (stepsToEntrance + stepsFromEntrance)
9889
9990 val newState = positions.toMutableList()
10091 newState[amphi] = finalPos
101- return listOf (totalCost to State (newState))
92+ return listOf (totalCost to State (numNumbers, newState))
10293 }
10394 }
10495
10596 private fun canGoTo (from : Int , to : Int ): Boolean {
106- val range = minOf(from+ 1 , to).. maxOf(from- 1 , to)
97+ val range = minOf(from + 1 , to).. maxOf(from - 1 , to)
10798 return ! positions.any { pos -> pos in range }
10899 }
109100}
110101
111102fun day23_1 (lines : List <String >): Any {
103+ // Ex part1
112104// val startState = listOf(room1[1], room4[1], room1[0], room3[0], room2[0], room3[1], room2[1], room4[0])
113- val startState = listOf (room2[1 ], room4[0 ], room1[0 ], room2[0 ], room1[1 ], room4[1 ], room3[0 ], room3[1 ])
114-
115-
116- // val startState = listOf(room1[1], room4[1], room1[0], 3, 9, room3[1], room2[1], room4[0])
105+ // val startState = listOf(room1[1], room4[1], room1[0], 3, room2[0], room3[1], room2[1], room4[0])
106+ // val start = State(2, startState)
107+
108+ // Part 1
109+ // val startState = listOf(room2[1], room4[0], room1[0], room2[0], room1[1], room4[1], room3[0], room3[1])
110+ // val start = State(2, startState)
111+
112+ // Ex Part 2
113+ // val startState = listOf(
114+ // room1[3], room3[2], room4[1], room4[3],
115+ // room1[0], room2[2], room3[0], room3[1],
116+ // room2[0], room2[1], room3[3], room4[2],
117+ // room1[1], room1[2], room2[3], room4[0]
118+ // )
119+ // val start = State(4, startState)
120+
121+ // Part 2
122+ val startState = listOf (
123+ room2[3 ], room3[2 ], room4[0 ], room4[1 ],
124+ room1[0 ], room2[0 ], room2[2 ], room3[1 ],
125+ room1[3 ], room2[1 ], room4[2 ], room4[3 ],
126+ room1[1 ], room1[2 ], room3[0 ], room3[3 ],
127+ )
128+ val start = State (4 , startState)
117129
118- val start = State (startState)
119130
120131 val visited = mutableSetOf<State >()
121132 val queue = PriorityQueue <Pair <Int , State >>(Comparator .comparing { it.first })
122133 queue.offer(0 to start)
123134
135+ var count = 0
136+
124137 while (queue.isNotEmpty()) {
138+ count++
125139 val u = queue.poll()
126140
127141 if (u.second.isFinished()) {
142+ println (" Searched: $count " )
128143 return u.first
129144 }
130145 if (u.second in visited) {
@@ -138,44 +153,27 @@ fun day23_1(lines: List<String>): Any {
138153 }
139154
140155 }
141-
142- // val moves = start.getPossibleMoves()
143- //
144156 return " failed"
145157
146- // is goal state
147-
148- // for each amphipod, generate moves
149- // if inside
150- // and nothing in front
151- // move out to all feasible spots
152- // where feasible is all left/right of entrance not blocked
153- // costs are moving out + dist from entrance
154- // if outside, only 0 or 1 move possible
155- // which is going in, or is blocked
156158}
157159
158160
159- fun day23_2 (lines : List <String >): Any {
160- return 2
161- }
162-
163161fun main () {
164-
165162 run (" 1" , fileName = " day23_dummy.txt" , func = ::day23_1)
166- // run("1", fileName = "day23_1.txt", func = ::day23_1)
167- // run("2", fileName = "day23_ex.txt", func = ::day23_2)
168- // run("2", fileName = "day23_1.txt", func = ::day23_2)
169163}
170164
171165/*
172166OUTPUT
173167======
174168
175- Done. Took 27ms to run
176- Result for 1: 1462
169+ Done. Took 2134ms to run
170+ Result for 1: 11608
171+ Copied to clipboard!
172+
177173
178- Done. Took 37ms to run
179- Result for 2: 1497
174+ Searched: 467459
175+ Done. Took 5960ms to run
176+ Result for 1: 46754
177+ Copied to clipboard!
180178
181179 */
0 commit comments