This repository has been archived by the owner on Jan 13, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day12.scala
52 lines (41 loc) · 1.93 KB
/
Day12.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package adventofcode.solutions
import adventofcode.Definitions.*
@main def Day12 = Day(12) { (input, part) =>
case class Row(row: IndexedSeq[Option[Boolean]], runLength: Seq[Int])
val rows = input.toLines.map {
case s"$lhs $rhs" =>
val row = lhs.map {
case '.' => Some(false)
case '#' => Some(true)
case '?' => None
}
Row(row, rhs.split(",").map(_.toInt).toSeq)
}
type Cache = Map[(Int, Int, Int), Long]
def arrangements(row: Row): Long =
def arrangements(patterns: Seq[Option[Boolean]], items: Seq[Int], patternsOffset: Int, itemsOffset: Int, slack: Int, cache: Cache): (Long, Cache) =
val key = (patternsOffset, itemsOffset, slack)
cache.get(key) match
case Some(value) => (value, cache)
case _ =>
val (result, newCache) = items match
case head +: tail =>
(0 to slack)
.filter(i => patterns.take(i).forall(!_.exists(identity))
&& patterns.drop(i).take(head).forall(_.forall(identity))
&& !patterns.drop(i + head).headOption.flatten.exists(identity)
)
.foldLeft((0L, cache)) { case ((sum, cache), i) =>
val offset = i + head + 1
val (add, newCache) = arrangements(patterns.drop(offset), tail, patternsOffset - offset, itemsOffset - 1, slack - i, cache)
(sum + add, newCache)
}
case _ => (if patterns.forall(!_.exists(identity)) then 1L else 0L, cache)
(result, newCache + (key -> result))
arrangements(row.row, row.runLength, 0, 0, row.row.size - (row.runLength.sum + row.runLength.size - 1), Map.empty)._1
def sum(rows: Seq[Row]): Long = rows.map(arrangements).sum
part(1) = sum(rows)
def unfold(row: Row, n: Int): Row =
Row(Seq.fill(n)(row.row).reduce(_ ++ Seq(None) ++ _), Seq.fill(n)(row.runLength).flatten)
part(2) = sum(rows.map(unfold(_, 5)))
}