Add day 12
This commit is contained in:
parent
506e288f61
commit
c60ed493d7
55
Day12.scala
Normal file
55
Day12.scala
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
package aoc.day12
|
||||||
|
|
||||||
|
import aoc._
|
||||||
|
import scala.collection.mutable
|
||||||
|
|
||||||
|
case class Record(input: String, groups: List[Int]):
|
||||||
|
lazy val possibleFills = loop(0, groups)
|
||||||
|
|
||||||
|
def unfold(times: Int) =
|
||||||
|
Record((1 to times).map(_ => input).mkString("?"), (1 to times).flatMap(_ => groups).toList)
|
||||||
|
|
||||||
|
private inline def canEmpty(pos: Char) = pos == '.' || pos == '?'
|
||||||
|
private inline def canFill(pos: Char) = pos == '#' || pos == '?'
|
||||||
|
|
||||||
|
private val memo = mutable.Map.empty[(Int, Int), Long]
|
||||||
|
private def loop(from: Int, groups: List[Int]): Long =
|
||||||
|
if from == input.length() then (if groups.isEmpty then 1 else 0)
|
||||||
|
else
|
||||||
|
memo.getOrElseUpdate(
|
||||||
|
(from, groups.length), {
|
||||||
|
// don't fill this group
|
||||||
|
val noFill = if canEmpty(input(from)) then loop(from + 1, groups) else 0
|
||||||
|
// fill this group
|
||||||
|
val doFill = groups match
|
||||||
|
case head :: next if from + head <= input.length =>
|
||||||
|
val slice = input.slice(from, from + head)
|
||||||
|
if slice.forall(canFill(_)) then
|
||||||
|
if from + head == input.length() then loop(from + head, next)
|
||||||
|
else if canEmpty(input(from + head)) then loop(from + head + 1, next)
|
||||||
|
else 0
|
||||||
|
else 0
|
||||||
|
case _ => 0
|
||||||
|
noFill + doFill
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
object Parser extends CommonParser:
|
||||||
|
val groups = repsep(num, ",")
|
||||||
|
val record = """[?#.]+""".r ~ groups ^^ { case (input ~ groups) => Record(input, groups) }
|
||||||
|
|
||||||
|
def apply(s: String) = parse(record, s).get
|
||||||
|
|
||||||
|
val records = lines.map(Parser(_)).toSeq
|
||||||
|
|
||||||
|
def part1 =
|
||||||
|
val result = records.map(_.possibleFills).sum
|
||||||
|
println(result)
|
||||||
|
|
||||||
|
def part2 =
|
||||||
|
val result = records.map(_.unfold(5).possibleFills).sum
|
||||||
|
println(result)
|
||||||
|
|
||||||
|
@main def Day12(part: Int) = part match
|
||||||
|
case 1 => part1
|
||||||
|
case 2 => part2
|
1000
inputs/day12.input
Normal file
1000
inputs/day12.input
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue