|
1 | 1 | package eu.sim642.adventofcode2025 |
2 | 2 |
|
| 3 | +import scala.annotation.tailrec |
3 | 4 | import scala.collection.mutable |
4 | 5 |
|
5 | 6 | object Day11 { |
@@ -58,7 +59,45 @@ object Day11 { |
58 | 59 | override object Part2 extends ViaMapPartSolution with Part2Devices |
59 | 60 | } |
60 | 61 |
|
61 | | - // TODO: path count product solution |
| 62 | + /** |
| 63 | + * Solution, which tries all permutations of vias and counts each one by multiplying adjacent steps. |
| 64 | + */ |
| 65 | + object PermutationSolution extends Solution { |
| 66 | + trait PermutationPartSolution extends PartSolution { |
| 67 | + def countPathsTo(devices: Devices)(to: Device): Device => Long = { |
| 68 | + val memo = mutable.Map.empty[Device, Long] |
| 69 | + |
| 70 | + def helper(device: Device): Long = { |
| 71 | + memo.getOrElseUpdate(device, { |
| 72 | + if (device == to) |
| 73 | + 1 |
| 74 | + else |
| 75 | + devices.getOrElse(device, Set.empty).map(helper).sum // need getOrElse for "out" when from is different, but reaches "out" |
| 76 | + }) |
| 77 | + } |
| 78 | + |
| 79 | + helper |
| 80 | + } |
| 81 | + |
| 82 | + override def countPaths(devices: Devices): Long = { |
| 83 | + val memo = mutable.Map.empty[Device, Device => Long] |
| 84 | + |
| 85 | + def countPathsFromTo(from: Device, to: Device): Long = // memoize by to, because same to will be reused |
| 86 | + memo.getOrElseUpdate(to, countPathsTo(devices)(to))(from) |
| 87 | + |
| 88 | + @tailrec |
| 89 | + def helper(prevDevice: Device, acc: Long, via: List[Device]): Long = via match { |
| 90 | + case Nil => acc * countPathsFromTo(prevDevice, to) |
| 91 | + case device :: newVia => helper(device, acc * countPathsFromTo(prevDevice, device), newVia) // TODO: optimize: stop when countPathsFromTo is zero |
| 92 | + } |
| 93 | + |
| 94 | + via.toList.permutations.map(helper(from, 1L, _)).sum // TODO: optimize: only one can be non-zero, stop on first |
| 95 | + } |
| 96 | + } |
| 97 | + |
| 98 | + override object Part1 extends PermutationPartSolution with Part1Devices |
| 99 | + override object Part2 extends PermutationPartSolution with Part2Devices |
| 100 | + } |
62 | 101 |
|
63 | 102 | def parseDevice(s: String): (Device, Seq[Device]) = s match { |
64 | 103 | case s"$key: $values" => key -> values.split(" ").toSeq |
|
0 commit comments