Skip to content

Instantly share code, notes, and snippets.

@waynejo
Last active June 4, 2021 13:47
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 waynejo/be8f70219e828bffe6a247257f3ea18d to your computer and use it in GitHub Desktop.
Save waynejo/be8f70219e828bffe6a247257f3ea18d to your computer and use it in GitHub Desktop.
import java.io.FileInputStream
import collection.immutable.HashMap
import scala.io.StdIn
case class Cup(value: Int, var next: Cup)
case class CupGroup(head: Cup, last: Cup):
def + (that: CupGroup): CupGroup =
last.next = that.head
CupGroup(head, that.last)
object Cup:
def build(inputs: Vector[Int]): Cup =
var head = Cup(inputs.head, null)
head.next = head
build(inputs.tail, head, head)
private def build(inputs: Vector[Int], head: Cup, last: Cup): Cup =
inputs.headOption match
case Some(v) =>
val cup = Cup(v, head)
last.next = cup
build(inputs.tail, head, cup)
case _ =>
head
def validateDestination(destination: Int, pickupHead: Cup, size: Int): Int =
if 1 > destination then
validateDestination(size, pickupHead, size)
else if pickupHead.value == destination || pickupHead.next.value == destination || pickupHead.next.next.value == destination then
validateDestination(destination - 1, pickupHead, size)
else
destination
def resolveBuffer(inputs: Cup, remain: Int, buffer: HashMap[Int, CupGroup]): HashMap[Int, CupGroup] =
if 0 == remain then
buffer
else
buffer.get(inputs.value) match
case Some(cupGroup) =>
val nextOfInput = inputs.next
inputs.next = cupGroup.head
cupGroup.last.next = nextOfInput
resolveBuffer(inputs.next, remain - 1, buffer.removed(inputs.value))
case _ =>
resolveBuffer(inputs.next, remain - 1, buffer)
def stepOfCrab(inputs: Cup, remainStep: Int, buffer: HashMap[Int, CupGroup], size: Int): (Cup, HashMap[Int, CupGroup]) =
val resolvedBuffer = resolveBuffer(inputs, 5, buffer)
if 0 == remainStep then
(inputs, resolvedBuffer)
else
val current = inputs
val pickup = CupGroup(inputs.next, inputs.next.next.next)
val remains = pickup.last.next
current.next = remains
val destination = validateDestination(current.value - 1, pickup.head, size)
val nextBuffer = resolvedBuffer.get(destination) match
case Some(cupGroup) =>
resolvedBuffer.updated(destination, pickup + cupGroup)
case _ =>
resolvedBuffer.updated(destination, pickup)
stepOfCrab(current.next, remainStep - 1, nextBuffer, size)
def findFirst(cup: Cup, buffer: HashMap[Int, CupGroup]): Cup =
val resolvedBuffer = resolveBuffer(cup, 2, buffer)
if 1 == cup.value then
cup
else
findFirst(cup.next, resolvedBuffer)
def solve23_1(inputs: Vector[Int]): Vector[Int] =
val (result, buffer) = stepOfCrab(Cup.build(inputs), 10, HashMap(), inputs.length)
def buildVector(acc: Vector[Int], cup: Cup, head: Cup): Vector[Int] =
if cup eq head then
acc
else
buildVector(acc :+ cup.value, cup.next, head)
val firstCup = findFirst(result, buffer)
buildVector(Vector(firstCup.value), firstCup.next, firstCup).tail
def solve23_2(inputs: Vector[Int], step: Int = 0): BigInt =
val validInputs = inputs ++ ((inputs.length + 1) to 1000000).toVector
val (result, buffer) = stepOfCrab(Cup.build(validInputs), 10000000, HashMap(), validInputs.length)
val firstCup = findFirst(result, buffer)
BigInt(firstCup.next.value) * BigInt(firstCup.next.next.value)
@main def solve23() =
val in = new FileInputStream("example23.in")
System.setIn(in)
val inputs = StdIn.readLine().trim.map(_.toInt - '0').toVector
println(solve23_1(inputs).mkString)
println(solve23_2(inputs))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment