package be.vandewalleh.aoc.days import be.vandewalleh.aoc.utils.input.Day import be.vandewalleh.aoc.utils.input.Groups private data class PlayedGame(val a: List, val b: List) @Day(22) class Day22(@Groups val input: List>) { private val one = input[0].drop(1).map { it.toInt() } private val two = input[1].drop(1).map { it.toInt() } fun part1(): Long { val oneDeque = ArrayDeque(one) val twoDeque = ArrayDeque(two) while (oneDeque.isNotEmpty() && twoDeque.isNotEmpty()) { val a = oneDeque.removeFirst() val b = twoDeque.removeFirst() if (a > b) { oneDeque.addLast(a) oneDeque.addLast(b) } else { twoDeque.addLast(b) twoDeque.addLast(a) } } val deque = if (oneDeque.isEmpty()) twoDeque else oneDeque return deque.score() } private fun ArrayDeque.score() = asReversed().mapIndexed { index, value -> (index + 1).toLong() * value.toLong() }.sum() fun part2(): Long { val oneDeque = ArrayDeque(one) val twoDeque = ArrayDeque(two) val winner = playGame(oneDeque, twoDeque) val deque = if (winner == 1) oneDeque else twoDeque return deque.score() } private fun playGame(one: ArrayDeque, two: ArrayDeque): Int { val playedGames = mutableSetOf() while (one.isNotEmpty() && two.isNotEmpty()) { if (!playedGames.add(PlayedGame(one.toList(), two.toList()))) return 1 val a = one.removeFirst() val b = two.removeFirst() val winner = when { one.size >= a && two.size >= b -> playGame( ArrayDeque(one.take(a)), ArrayDeque(two.take(b)) ) a > b -> 1 else -> 2 } if (winner == 1) { one.addLast(a) one.addLast(b) } else { two.addLast(b) two.addLast(a) } } return if (one.isEmpty()) 2 else 1 } }