Cleanup
This commit is contained in:
@@ -4,15 +4,8 @@ import scala.collection.mutable
|
|||||||
|
|
||||||
object Memo:
|
object Memo:
|
||||||
def Y[I, O](f: (I, I => O) => O): I => O =
|
def Y[I, O](f: (I, I => O) => O): I => O =
|
||||||
var yf: I => O = null
|
lazy val yf: I => O = Memo(f(_, yf(_))); yf
|
||||||
yf = Memo(f(_, yf(_)))
|
|
||||||
yf
|
|
||||||
|
|
||||||
class Memo[-I, +O](f: I => O) extends (I => O):
|
class Memo[-I, +O](f: I => O) extends (I => O):
|
||||||
private[this] val memo = mutable.Map.empty[I, O]
|
private[this] val memo = mutable.Map.empty[I, O]
|
||||||
|
def apply(i: I): O = { lazy val o = f(i); memo.getOrElseUpdate(i, o) }
|
||||||
def apply(i: I): O =
|
|
||||||
if memo.contains(i) then memo(i)
|
|
||||||
else {
|
|
||||||
val o = f(i); memo(i) = o; o
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ object Day16 extends Solver(16):
|
|||||||
val all = mutable.Set(endPose)
|
val all = mutable.Set(endPose)
|
||||||
var cur = Set(endPose)
|
var cur = Set(endPose)
|
||||||
|
|
||||||
println(start)
|
|
||||||
while cur.nonEmpty do
|
while cur.nonEmpty do
|
||||||
cur = cur.filter(_ != Pose(start, Direction.Right)).flatMap(ancestor(_))
|
cur = cur.filter(_ != Pose(start, Direction.Right)).flatMap(ancestor(_))
|
||||||
all.addAll(cur)
|
all.addAll(cur)
|
||||||
|
|||||||
@@ -2,38 +2,23 @@ package dev.ctsk.aoc.days
|
|||||||
|
|
||||||
import dev.ctsk.aoc.*
|
import dev.ctsk.aoc.*
|
||||||
|
|
||||||
import scala.util.boundary
|
|
||||||
import scala.util.boundary.break
|
|
||||||
|
|
||||||
object Day19 extends Solver(19):
|
object Day19 extends Solver(19):
|
||||||
|
|
||||||
def pre(input: os.ReadablePath): (Trie, Seq[String]) =
|
def pre(input: os.ReadablePath): (Trie, Seq[String]) =
|
||||||
val Array(rules_, words_) = os.read(input).split("\n\n")
|
val Array(rules_, words_) = os.read(input).split("\n\n")
|
||||||
val trie = Trie()
|
val trie = Trie()
|
||||||
for rule <- rules_.split(", ") do trie.insert(rule)
|
for rule <- rules_.split(", ") do trie.insert(rule)
|
||||||
(trie, words_.linesIterator.toSeq)
|
(trie, words_.linesIterator.toSeq)
|
||||||
|
|
||||||
def part1(trie: Trie, words: Seq[String]): Int =
|
private def arrangements(trie: Trie, word: String): Long =
|
||||||
def valid(word: String, inj: String => Boolean): Boolean =
|
def rec(offset: Int, inj: Int => Long): Long =
|
||||||
if word.isEmpty then return true
|
if offset == word.length then return 1L
|
||||||
boundary:
|
trie.prefixes(word, offset).map(inj).sum
|
||||||
for p <- trie.prefixes(word) do
|
Memo.Y(rec)(0)
|
||||||
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
|
|
||||||
|
|
||||||
override def run(input: os.ReadablePath): (Timings, Solution) =
|
override def run(input: os.ReadablePath): (Timings, Solution) =
|
||||||
val (pre_time, (trie, words)) = timed { pre(input) }
|
val (pre_time, (trie, words)) = timed { pre(input) }
|
||||||
val (p1_time, p1) = timed { part1(trie, words) }
|
val (p1_time, p1) = timed { words.count(arrangements(trie, _) > 0) }
|
||||||
val (p2_time, p2) = timed { part2(trie, words) }
|
val (p2_time, p2) = timed { words.map(arrangements(trie, _)).sum }
|
||||||
|
|
||||||
(
|
(
|
||||||
Timings(pre_time, p1_time, p2_time),
|
Timings(pre_time, p1_time, p2_time),
|
||||||
|
|||||||
Reference in New Issue
Block a user