Skip to content

Commit

Permalink
Day 21 part 2 test passing, main input StackOverflow
Browse files Browse the repository at this point in the history
  • Loading branch information
kohloderso committed Dec 21, 2023
1 parent e7231bf commit 39bdd7b
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 13 deletions.
75 changes: 70 additions & 5 deletions src/solutions23/Day21.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,87 @@ fun main() {
val gardenGrid = input.map { line -> line.map { when(it) {'#' -> false; else -> true} }.toTypedArray() }.toTypedArray()
val startPoint = findStartPoint(input)
// compute shortest paths
val distArray = dijkstra(gardenGrid, startPoint.first, startPoint.second)
val distArray = dijkstra(gardenGrid, ArrayDeque(setOf(Triple(0,startPoint.first, startPoint.second))))
// count all even values which are <= steps and have same parity as steps
val result = distArray.sumOf { it.count { d -> d <= steps && d % 2 == steps % 2 } }
return result
}

fun part2(input: List<List<String>>): Long {
return 0
fun part2(input: List<String>, steps: Int): Long {
val gardenGrid = input.map { line -> line.map { when(it) {'#' -> false; else -> true} }.toTypedArray() }.toTypedArray()
val visitedGrids = mutableSetOf<Pair<Int, Int>>()
var counter = 0L
val startPoint = findStartPoint(input)

fun considerGrid(i: Int, j: Int, initValues: ArrayDeque<Triple<Int, Int, Int>>) {
if(visitedGrids.contains(i to j)) return
// compute distances for this grid
val distArray = dijkstra(gardenGrid, initValues)
// count all even values which are <= steps and have same parity as steps
val result = distArray.sumOf { it.count { d -> d <= steps && d % 2 == steps % 2 } }
counter += result
visitedGrids.add(i to j)
if(result == 0) return // no chance of finding new solutions here
// consider neighbours
if(i >= 0 && !visitedGrids.contains(i+1 to j)) { // check down
// the top row can be initialized with the bottom row of the current grid + 1
val nextInit = ArrayDeque<Triple<Int, Int, Int>>()
for(col in distArray.indices) {
val dist = distArray[0][col] + 1
if(dist <= steps)
nextInit.add(Triple(dist, distArray.size-1, col))
}
if(nextInit.any { it.first <= steps })
considerGrid(i + 1, j, nextInit)
}
if(i <= 0 && !visitedGrids.contains(i-1 to j)) { // check to the up
// the bottom row can be initialized with the top row of the current grid + 1
val nextInit = ArrayDeque<Triple<Int, Int, Int>>()
for(col in distArray[0].indices) {
val dist = distArray[distArray.size-1][col] + 1
if(dist <= steps)
nextInit.add(Triple(dist, 0, col))
}
if(nextInit.any { it.first <= steps })
considerGrid(i - 1, j, nextInit)
}
if(j >= 0 && !visitedGrids.contains(i to j+1)) { // check right
// the left column can be initialized with the rightmost column of the current grid + 1
val nextInit = ArrayDeque<Triple<Int, Int, Int>>()
for(row in distArray.indices) {
val dist = distArray[row][distArray[0].size-1] + 1
if(dist <= steps)
nextInit.add(Triple(dist, row, 0))
}
if(nextInit.any { it.first <= steps })
considerGrid(i, j+1, nextInit)
}
if(j <= 0 && !visitedGrids.contains(i to j-1)) { // check left
// the right column can be initialized with the leftmost column of the current grid + 1
val nextInit = ArrayDeque<Triple<Int, Int, Int>>()
for(row in distArray.indices) {
val dist = distArray[row][0] + 1
if(dist <= steps)
nextInit.add(Triple(dist, row, distArray[0].size - 1))
}
if(nextInit.any { it.first <= steps })
considerGrid(i, j-1, nextInit)
}
}
considerGrid(0, 0, ArrayDeque(setOf(Triple(0,startPoint.first, startPoint.second))))
return counter
}

val testInput = parseLines("Day21_test")

check(part1(testInput, 6) == 16)
//check(part2(testInput) == 167409079868000L)
check(part2(testInput,6) == 16L)
check(part2(testInput,10) == 50L)
check(part2(testInput,50) == 1594L)
check(part2(testInput,100) == 6536L)


val input = parseLines("Day21")
println(part1(input, 64))
//println(part2(input))
println(part2(input, 26501365))
}
12 changes: 4 additions & 8 deletions src/solutions23/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -95,30 +95,26 @@ fun lcmList(xs: List<Long>): Long = xs.fold(1) {a, x -> lcm(a,x) }
/**
* Simple generic Dijkstra implementation where the input is a grid consisting of
* two types of tiles: the ones which are allowed are true, the ones which are blocked are set to false.
* Also takes sorted queue of initial coordinates with their distance as input.
* Returns a grid of the same size as the input containing the shortest paths from the start.
*/
fun dijkstra(grid: Array<Array<Boolean>>, startX: Int, startY: Int): Array<Array<Int>> {
fun dijkstra(grid: Array<Array<Boolean>>, nextNodes: ArrayDeque<Triple<Int, Int, Int>>): Array<Array<Int>> {
val distArray = Array(grid.size) { Array(grid[0].size) { Int.MAX_VALUE } }
distArray[startX][startY] = 0
val nextNodes = ArrayDeque<Triple<Int, Int, Int>>()
nextNodes.add(Triple(0, startX, startY))
while (nextNodes.isNotEmpty()) {
val (dist, i, j) = nextNodes.removeFirst()
if(distArray[i][j] <= dist) continue
distArray[i][j] = dist
// check the four direct neighbours
if (i - 1 >= 0 && grid[i - 1][j] && distArray[i - 1][j] > dist + 1) {
distArray[i - 1][j] = dist + 1
nextNodes.add(Triple(dist + 1, i - 1, j))
}
if (i + 1 < grid.size && grid[i + 1][j] && distArray[i + 1][j] > dist + 1) {
distArray[i + 1][j] = dist + 1
nextNodes.add(Triple(dist + 1, i + 1, j))
}
if (j - 1 >= 0 && grid[i][j - 1] && distArray[i][j - 1] > dist + 1) {
distArray[i][j - 1] = dist + 1
nextNodes.add(Triple(dist + 1, i, j - 1))
}
if (j + 1 < grid[0].size && grid[i][j + 1] && distArray[i][j + 1] > dist + 1) {
distArray[i][j + 1] = dist + 1
nextNodes.add(Triple(dist + 1, i, j + 1))
}
}
Expand Down

0 comments on commit 39bdd7b

Please sign in to comment.