Skip to content

Instantly share code, notes, and snippets.

@sungkmi
Last active June 4, 2021 18:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sungkmi/6f5f4f9e059d7bec8ce31d9ef62aaa9c to your computer and use it in GitHub Desktop.
Save sungkmi/6f5f4f9e059d7bec8ce31d9ef62aaa9c to your computer and use it in GitHub Desktop.
package sungkmi.aoc2020.day23
case class CupCircle(
cups: Vector[Int]
)
object CupCircle:
def apply(cups: Vector[Int], current: Int): CupCircle =
val (f, e) = cups.splitAt(cups.indexOf(current) + 1)
CupCircle(e ++ f)
def parse(s: String): CupCircle =
val cups: Vector[Int] = s.map(_ - '0').toVector
CupCircle(cups.tail :+ cups.head)
extension (c: CupCircle)
def pickup: Vector[Int] = c.cups.take(3)
def destination: Int =
@annotation.tailrec
def loop(n: Int): Int =
if pickup contains n then loop(n - 1)
else if n < 1 then loop(c.cups.size)
else n
loop(c.cups.last - 1)
def move: CupCircle =
val (pickup, remainder) = c.cups.splitAt(3)
// println(s"===> $pickup / $remainder")
val destIndex = remainder.indexOf(c.destination)
if (destIndex == -1) then println(s"===> wrong dest: ${c.destination}")
val (front1, end1) = remainder.splitAt(destIndex + 1)
// println(s"===> $front1 / $end1")
val cups1 = front1.tail ++ pickup ++ end1 :+ front1.head
// println(s"===> $cups1")
CupCircle(cups1)
def solve1(s: String): String =
val cups1 = (1 to 100).foldLeft(CupCircle.parse(s))((cups, _) => cups.move)
val indexOf1 = cups1.cups.indexOf(1)
(cups1.cups ++ cups1.cups).drop(indexOf1 + 1).take(cups1.cups.size - 1).mkString
def solve2(s: String): BigInt =
val CupCircle(cups0) = CupCircle.parse(s)
val cups = CupCircle(cups0 ++ ((cups0.size + 1) to 1000000))
val cups1: Vector[Int] = (1 to 10000000).foldLeft(cups)((cups, _) => cups.move).cups
val indexOf1 = cups1.indexOf(1)
val n1 = cups1((indexOf1 + 1) % 10000000)
val n2 = cups1((indexOf1 + 2) % 10000000)
BigInt(n1) * BigInt(n2)
@main def part1: Unit =
val ans = solve1(input)
println(ans)
@main def part2: Unit =
val ans = solve2(input)
println(ans)
lazy val input: String = """487912365"""
package sungkmi.aoc2020.day23
import scala.collection.immutable.Queue
class Day23Test extends munit.FunSuite {
val testInput = """389125467"""
val cups1 = CupCircle(Vector(3,8,9,1,2,5,4,6,7), 3)
val cups2 = CupCircle(Vector(3,2,8,9,1,5,4,6,7), 2)
val cups3 = CupCircle(Vector(3,2,5,4,6,7,8,9,1), 5)
val cups4 = CupCircle(Vector(7,2,5,8,9,1,3,4,6), 8)
val cups5 = CupCircle(Vector(3,2,5,8,4,6,7,9,1), 4)
val cups6 = CupCircle(Vector(9,2,5,8,4,1,3,6,7), 1)
val cups7 = CupCircle(Vector(7,2,5,8,4,1,9,3,6), 9)
val cups8 = CupCircle(Vector(8,3,6,7,4,1,9,2,5), 2)
val cups9 = CupCircle(Vector(7,4,1,5,8,3,9,2,6), 6)
val cups10 = CupCircle(Vector(5,7,4,1,8,3,9,2,6), 5)
val cupsF = CupCircle(Vector(5,8,3,7,4,1,9,2,6), 8)
test("day23 parse") {
assertEquals(CupCircle.parse(testInput), cups1)
}
test("day23 CupCircle.pickup") {
assertEquals(cups1.pickup, Vector(8,9,1))
assertEquals(cups2.pickup, Vector(8,9,1))
assertEquals(cups3.pickup, Vector(4,6,7))
assertEquals(cups4.pickup, Vector(9,1,3))
assertEquals(cups5.pickup, Vector(6,7,9))
assertEquals(cups6.pickup, Vector(3,6,7))
assertEquals(cups7.pickup, Vector(3,6,7))
assertEquals(cups8.pickup, Vector(5,8,3))
assertEquals(cups9.pickup, Vector(7,4,1))
assertEquals(cups10.pickup, Vector(7,4,1))
}
test("day23 CupCircle.destination") {
assertEquals(cups1.destination, 2)
assertEquals(cups2.destination, 7)
assertEquals(cups3.destination, 3)
assertEquals(cups4.destination, 7)
assertEquals(cups5.destination, 3)
assertEquals(cups6.destination, 9)
assertEquals(cups7.destination, 8)
assertEquals(cups8.destination, 1)
assertEquals(cups9.destination, 5)
assertEquals(cups10.destination, 3)
}
//test("day23 CupCircle.move") {
// assertEquals(cups2.move, cups3)
//}
test("day23 CupCircle.move") {
assertEquals(cups1.move, cups2)
assertEquals(cups2.move, cups3)
assertEquals(cups3.move, cups4)
assertEquals(cups4.move, cups5)
assertEquals(cups5.move, cups6)
assertEquals(cups6.move, cups7)
assertEquals(cups7.move, cups8)
assertEquals(cups8.move, cups9)
assertEquals(cups9.move, cups10)
assertEquals(cups10.move, cupsF)
}
test("day23 solve1") {
assertEquals(solve1(testInput), "67384529")
}
//test("day23 solve2") {
// assertEquals(solve2("389125467"), BigInt("149245887792"))
//}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment