This commit is contained in:
Christian
2024-12-19 10:14:53 +01:00
parent 0198ead034
commit 57852ccfc1
3 changed files with 9 additions and 32 deletions

View File

@@ -4,15 +4,8 @@ import scala.collection.mutable
object Memo:
def Y[I, O](f: (I, I => O) => O): I => O =
var yf: I => O = null
yf = Memo(f(_, yf(_)))
yf
lazy val yf: I => O = Memo(f(_, yf(_))); yf
class Memo[-I, +O](f: I => O) extends (I => O):
private[this] val memo = mutable.Map.empty[I, O]
def apply(i: I): O =
if memo.contains(i) then memo(i)
else {
val o = f(i); memo(i) = o; o
}
def apply(i: I): O = { lazy val o = f(i); memo.getOrElseUpdate(i, o) }

View File

@@ -51,7 +51,6 @@ object Day16 extends Solver(16):
val all = mutable.Set(endPose)
var cur = Set(endPose)
println(start)
while cur.nonEmpty do
cur = cur.filter(_ != Pose(start, Direction.Right)).flatMap(ancestor(_))
all.addAll(cur)

View File

@@ -2,38 +2,23 @@ package dev.ctsk.aoc.days
import dev.ctsk.aoc.*
import scala.util.boundary
import scala.util.boundary.break
object Day19 extends Solver(19):
def pre(input: os.ReadablePath): (Trie, Seq[String]) =
val Array(rules_, words_) = os.read(input).split("\n\n")
val trie = Trie()
for rule <- rules_.split(", ") do trie.insert(rule)
(trie, words_.linesIterator.toSeq)
def part1(trie: Trie, words: Seq[String]): Int =
def valid(word: String, inj: String => Boolean): Boolean =
if word.isEmpty then return true
boundary:
for p <- trie.prefixes(word) do
if inj(word.slice(p, word.length)) then break(true)
false
words.count(Memo.Y(valid))
def part2(trie: Trie, words: Seq[String]): Long =
def valid(word: String, inj: String => Long): Long =
if word.isEmpty then return 1L
trie.prefixes(word).map(p => inj(word.slice(p, word.length))).sum
words.map(Memo.Y(valid)).sum
private def arrangements(trie: Trie, word: String): Long =
def rec(offset: Int, inj: Int => Long): Long =
if offset == word.length then return 1L
trie.prefixes(word, offset).map(inj).sum
Memo.Y(rec)(0)
override def run(input: os.ReadablePath): (Timings, Solution) =
val (pre_time, (trie, words)) = timed { pre(input) }
val (p1_time, p1) = timed { part1(trie, words) }
val (p2_time, p2) = timed { part2(trie, words) }
val (p1_time, p1) = timed { words.count(arrangements(trie, _) > 0) }
val (p2_time, p2) = timed { words.map(arrangements(trie, _)).sum }
(
Timings(pre_time, p1_time, p2_time),