Skip to content

Instantly share code, notes, and snippets.

@eugene70
Created May 28, 2021 13:46
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 eugene70/ae7c73607368815f4c4972548d4a23e0 to your computer and use it in GitHub Desktop.
Save eugene70/ae7c73607368815f4c4972548d4a23e0 to your computer and use it in GitHub Desktop.
package aoc2020
import scala.annotation.tailrec
object Day22:
type InputType = (CardDeck, CardDeck)
type CardDeck = Seq[Int]
@main def runDay22: Unit =
val testData = time("testReady", () => ready(testInput))
time("tesPart1", () => part1(testData)) // should be 306
time("testPart2", () => part2(testData)) // shuld be 291
val data = time("ready", () => ready(input))
time("part1", () => part1(data))
time("part2", () => part2(data))
private def ready(input: String): InputType =
val list = input
.split("""\n\s*\n""")
.map(_.linesIterator.drop(1).map(_.toInt).toSeq)
.toList
(list(0), list(1))
private def part1(data: InputType): Long =
eval(round(0, data, data))
@tailrec
def round(depth: Long, orgDecks: InputType, decks: InputType): InputType =
if (depth > 1000) return decks
if (decks._1.length == 0 || decks._2.length == 0) return decks
round(depth + 1, orgDecks,
if (decks._1.head > decks._2.head) (decks._1.tail :+ decks._1.head :+ decks._2.head, decks._2.tail)
else (decks._1.tail, decks._2.tail :+ decks._2.head :+ decks._1.head)
)
def eval(decks: InputType) =
val deck = if (decks._1.length > 0) decks._1 else decks._2
val max = deck.length
deck.zipWithIndex
.map((a, b) => a * (max - b))
.sum
@tailrec
def round2(decks: InputType): InputType =
if (decks._1.length == 0 || decks._2.length == 0) return decks
round2(
if (winFirst(decks)) (decks._1.tail :+ decks._1.head :+ decks._2.head, decks._2.tail)
else (decks._1.tail, decks._2.tail :+ decks._2.head :+ decks._1.head)
)
def winFirst(decks: InputType) =
if (decks._1.head < decks._1.length && decks._2.head < decks._2.length) {
subgame((decks._1.drop(1).take(decks._1.head), decks._2.drop(1).take(decks._2.head)))
}
else
decks._1.head > decks._2.head
def subgame(decks: InputType) =
round(0, decks, decks)._1.length > 0
private def part2(data: InputType): Long =
eval(round2(data))
private val testInput =
"""Player 1:
|9
|2
|6
|3
|1
|
|Player 2:
|5
|8
|4
|7
|10
|""".stripMargin
private val input =
"""Player 1:
|28
|13
|25
|16
|38
|3
|14
|6
|29
|2
|47
|20
|35
|43
|30
|39
|21
|42
|50
|48
|23
|11
|34
|24
|41
|
|Player 2:
|27
|37
|9
|10
|17
|31
|19
|33
|40
|12
|32
|1
|18
|36
|49
|46
|26
|4
|45
|8
|15
|5
|44
|22
|7
|""".stripMargin
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment