Skip to content

Commit

Permalink
feat: 2015 day 19
Browse files Browse the repository at this point in the history
  • Loading branch information
scarf005 committed Nov 3, 2024
1 parent 17bd2a8 commit d63c931
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 0 deletions.
53 changes: 53 additions & 0 deletions 2015/day19.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package `2015`.day19

import prelude.*

type Replacements = Map[String, Set[String]]

extension (s: String)
def replaceMolecules(replacementsMap: Replacements) =
(for
(from, tos) <- replacementsMap
to <- tos
yield s.transition(from, to)).flatten.toSet

def transition(from: String, to: String) =
s.sliding(from.length)
.zipWithIndex
.collect { case (`from`, i) => s.patch(i, to, from.length) }
.toSet

def part1(molecule: String, reqs: Replacements) =
molecule.replaceMolecules(reqs).size

def part2(molecule: String, reqs: Replacements) =
val revReqs = reqs.toVector
.flatMap { (key, values) => values.map(value => value -> key) }
.groupMap(_._1)(_._2)
.view
.mapValues(_.toSet)
.toMap

val keepBest = 5
def step(candidates: Vector[String]) = candidates
.flatMap(_.replaceMolecules(revReqs))
.sortBy(_.length)
.take(keepBest)

LazyList.iterate(Vector(molecule))(step).takeWhile(!_.contains("e")).size

@main def main() =
val input = fromFile(".cache/2015/19.txt").getLines.toVector

val molecule = input.last
val reqs = input
.dropRight(2)
.map(_.trim)
.collect { case s"$from => $to" => from -> to }
.groupMap(_._1)(_._2)
.view
.mapValues(_.toSet)
.toMap

println(part1(molecule, reqs))
println(part2(molecule, reqs))
40 changes: 40 additions & 0 deletions 2015/day19.test.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package `2015`.day19

import prelude.*
import munit.FunSuite

class Part1 extends FunSuite:
test("char"):
val replacements = Map(
"H" -> Set("HO", "OH"),
"O" -> Set("HH"),
)
assertEquals(
"HOH".replaceMolecules(replacements),
Set("HOOH", "HOHO", "OHOH", "HOOH", "HHHH"),
)

test("string"):
val replacements = Map(
"HO" -> Set("!!!"),
"H" -> Set("HO", "OH"),
"O" -> Set("HH"),
)
assertEquals(
"HOH".replaceMolecules(replacements),
Set("!!!H", "HOOH", "HOHO", "OHOH", "HOOH", "HHHH"),
)

test("do not consider surrounding characters"):
assertEquals("H2O".replaceMolecules(Map("H" -> Set("OO"))), Set("OO2O"))

class Part2 extends FunSuite:
test("example"):
val replacements = Map(
"e" -> Set("H", "O"),
"H" -> Set("HO", "OH"),
"O" -> Set("HH"),
)

assertEquals(part2("HOH", replacements), 3)
assertEquals(part2("HOHOHO", replacements), 6)

0 comments on commit d63c931

Please sign in to comment.