Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: 2015 day 17
Browse files Browse the repository at this point in the history
scarf005 committed Oct 2, 2024
1 parent 0389e72 commit f72d102
Showing 2 changed files with 76 additions and 0 deletions.
60 changes: 60 additions & 0 deletions 2015/day17.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package `2015`.day17

import prelude.*
import scala.collection.mutable.Map

trait Pretty[A]:
extension (x: A) inline def pretty: String

inline given [A]: Pretty[IterableOnce[A]] with
extension (x: IterableOnce[A])
inline def pretty = x.iterator.mkString("[", ", ", "]")

extension [A](x: Iterable[A])
def combinationsRepeating(size: Int): Iterator[Seq[A]] =
x.zipWithIndex.toSeq.combinations(size).map(_.map(_._1))

trait Logger:
def log(msg: => Any): Unit

given Logger = NoopLogger

object NoopLogger extends Logger:
def log(msg: => Any): Unit = {}

object PrintLogger extends Logger:
def log(msg: => Any): Unit = println(msg)

def part1(target: Int, containers: Iterable[Int])(using logger: Logger) =
val dp = Map[Int, Int](0 -> 1)
logger.log(s"target: $target, containers: $containers, dp: ${dp.pretty}")

for currentSize <- containers do
for nextSize <- (target to currentSize by -1) do
for x <- dp.get(nextSize - currentSize) do
dp(nextSize) = dp.getOrElse(nextSize, 0) + x
logger.log(
f"ways to fit $nextSize%2dL => using $currentSize%2dL: x${dp(nextSize)} ($x%2d ways to fit leftover ${nextSize - currentSize}%2dL), dp: ${dp.pretty}",
)
dp(target)

def part2(target: Int, containers: Seq[Int])(using logger: Logger) =
def matches(kinds: Int) =
containers
.combinationsRepeating(kinds)
.tapEach(logger.log(_))
.count(_.sum == target)
.tap(logger.log(_))

(1 to containers.size)
.map(matches)
.tapEach(logger.log(_))
.find(_ > 0)
.getOrElse(throw new Exception("no match found"))

@main def main() =
val containers = fromFile(".cache/2015/17.txt").getLines.map(_.toInt).toSeq
val target = 150

println(part1(target, containers))
println(part2(target, containers))
16 changes: 16 additions & 0 deletions 2015/day17.test.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package `2015`.day17

import prelude.*
import munit.FunSuite
import `2015`.day17.*


class Tests extends FunSuite:
// given Logger = PrintLogger
test("part 1"):
val res = part1(target = 25, containers = Seq(20, 15, 10, 5, 5))
assertEquals(res, 4)

test("part2"):
val res = part2(target = 25, containers = Seq(20, 15, 10, 5, 5))
assertEquals(res, 3)

0 comments on commit f72d102

Please sign in to comment.