Skip to content

Commit

Permalink
Utilize Arrow memoization (#285)
Browse files Browse the repository at this point in the history
It's not strictly faster than my own cache; but I hadn't used it before,
so wanted to give it a try. It's quite simple!
  • Loading branch information
peckb1 authored Dec 22, 2024
1 parent 97bd23a commit af9e41c
Showing 1 changed file with 23 additions and 34 deletions.
57 changes: 23 additions & 34 deletions src/main/kotlin/me/peckb/aoc/_2024/calendar/day21/Day21.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package me.peckb.aoc._2024.calendar.day21

import javax.inject.Inject
import arrow.core.memoize
import me.peckb.aoc.generators.InputGenerator.InputGeneratorFactory
import java.util.LinkedList
import javax.inject.Inject
import kotlin.math.sign

class Day21 @Inject constructor(
Expand All @@ -18,76 +19,72 @@ class Day21 @Inject constructor(

private fun solve(input: Sequence<String>, indirections: Int) : Long {
return input.sumOf { code ->
val length = getLength(NUMERIC_PAD, code, indirections)
val length = memoizedGetLength(NUMERIC_PAD, code, indirections)
val size = code.take(3).toLong()

length * size
}
}

private fun getLength(keyPad: Map<Char, Pair<Int, Int>>, code: String, indirections: Int): Long {
val lengthKey = LengthKey(keyPad.size, code, indirections)
private val memoizedGetLength = ::getLength.memoize()

if (LENGTH_CACHE.containsKey(lengthKey)) {
return LENGTH_CACHE[lengthKey]!!
}
private val memoizedPaths = ::paths.memoize()

private fun getLength(keyPad: Map<Char, Pair<Int, Int>>, code: String, indirections: Int): Long {
if (indirections == 0) {
return code.length.toLong().also { LENGTH_CACHE[lengthKey] = it }
return code.length.toLong()
}

val minLength = "A${code}".toList()
.windowed(2)
.sumOf { (s, e) ->
paths(keyPad, s, e).minOf { getLength(DIRECTION_PAD, "${it}A", indirections - 1) }
memoizedPaths(keyPad, s, e).minOf { memoizedGetLength(DIRECTION_PAD, "${it}A", indirections - 1) }
}

return minLength.also { LENGTH_CACHE[lengthKey] = it }
return minLength
}

private fun paths(keyPad: Map<Char, Pair<Int, Int>>, start: Char, end: Char): List<String> {
val pathKey = PathKey(keyPad.size, start, end)

if (PATHS_CACHE.containsKey(pathKey)) {
return PATHS_CACHE[pathKey]!!
}

val paths = mutableListOf<String>()

val partialPaths = LinkedList<Pair<Pair<Int, Int>, String>>().apply {
add(keyPad[start]!! to "")
}

pathGeneration@ while(partialPaths.isNotEmpty()) {
val (position, path) = partialPaths.poll()

val target = keyPad[end]!!

if (position == target) {
paths.add(path)
continue@pathGeneration
}

val yDelta = target.second - position.second
if (yDelta != 0) {
val newPoint = position.first to position.second + yDelta.sign
val (yDelta, xDelta) = target - position

if (xDelta != 0) {
val newPoint = position.first to position.second + xDelta.sign
if (newPoint in keyPad.values) {
val dir = if (yDelta > 0) { ">" } else { "<" }
val dir = if (xDelta > 0) { ">" } else { "<" }
partialPaths.add(newPoint to "$path$dir")
}
}

val xDelta = target.first - position.first
if (xDelta != 0) {
val newPoint = position.first + xDelta.sign to position.second
if (yDelta != 0) {
val newPoint = position.first + yDelta.sign to position.second
if (newPoint in keyPad.values) {
val dir = if (xDelta > 0) { "v" } else { "^" }
val dir = if (yDelta > 0) { "v" } else { "^" }
partialPaths.add(newPoint to "$path$dir")
}
}
}

return paths.also { PATHS_CACHE[pathKey] = it }
return paths
}

private operator fun Pair<Int, Int>.minus(other: Pair<Int, Int>) =
this.first - other.first to this.second - other.second

companion object {
val NUMERIC_PAD = mapOf(
'7' to (0 to 0), '8' to (0 to 1), '9' to (0 to 2),
Expand All @@ -100,13 +97,5 @@ class Day21 @Inject constructor(
'^' to (0 to 1), 'A' to (0 to 2),
'<' to (1 to 0), 'v' to (1 to 1), '>' to (1 to 2)
)

val LENGTH_CACHE = mutableMapOf<LengthKey, Long>()

val PATHS_CACHE = mutableMapOf<PathKey, List<String>>()
}
}

data class LengthKey(val padIndicator: Int, val pattern: String, val robots: Int)

data class PathKey(val padIndicator: Int, val start: Char, val end: Char)

0 comments on commit af9e41c

Please sign in to comment.