-
-
Save waynejo/be8f70219e828bffe6a247257f3ea18d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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