From f3546cfc84dbbcba619e8d3aa47a757be14fca72 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Thu, 14 Dec 2023 16:23:15 +0100 Subject: [PATCH] Day 14: use direct binary split instead of 2^n calculation --- Day14.scala | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/Day14.scala b/Day14.scala index bb44e76..132ebf0 100644 --- a/Day14.scala +++ b/Day14.scala @@ -43,23 +43,17 @@ def part1 = // part 2 object Cycling: - private val memo = mutable.Map.empty[(Board, Int), Board] - private def getPower(b: Board, p: Int): Board = // b.cycle 2^p times - memo.getOrElseUpdate( - (b, p), { - if p == 0 then b.cycle - else getPower(getPower(b, p - 1), p - 1) - } - ) + private val memo = mutable.Map.empty[(Board, Long), Board] def apply(b: Board, times: Long): Board = - @scala.annotation.tailrec - def loop(b: Board, i: Int): Board = - val pow = 1L << i - if pow > times then b - else if (pow & times) > 0 then loop(getPower(b, i), i + 1) - else loop(b, i + 1) - loop(b, 0) + if times == 0 then b + else + memo.getOrElseUpdate( + (b, times), { + val twice = apply(apply(b, times / 2), times / 2) + if times % 2 == 0 then twice else twice.cycle + } + ) def part2 = println(Cycling(board, 1_000_000_000).load)