From c957038fd78df0f1e8d2d08ff0943c3e67e1adf2 Mon Sep 17 00:00:00 2001 From: Sven Weidauer Date: Tue, 21 Dec 2021 11:25:58 +0100 Subject: [PATCH] Day 21 Part 2 --- day21.swift | 84 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 19 deletions(-) diff --git a/day21.swift b/day21.swift index 78d6bb5..90e9c82 100644 --- a/day21.swift +++ b/day21.swift @@ -2,54 +2,100 @@ struct Day21: Puzzle { func run() { part1() + part2() } + let player1 = Player(position: 6) + let player2 = Player(position: 7) func part1() { var die = Die() - var player1 = Player(position: 6) - var player2 = Player(position: 7) + var player1 = player1 + var player2 = player2 while true { - if player1.move(die.roll3()) { + if player1.move(die.roll3()) >= 1000 { print("Part 1: Player 1 won. ", die.rolls * player2.score) break } - if player2.move(die.roll3()) { + if player2.move(die.roll3()) >= 1000 { print("Part 1: Player 2 won. ", die.rolls * player1.score) break } } } - struct Player { + func part2() { + var universes: [Universe: Int] = [Universe(player1: player1, player2: player2): 1] + var player1Wins = 0 + var player2Wins = 0 + while !universes.isEmpty { + var newUniverses: [Universe: Int] = [:] + for (universe, universeCount) in universes { + for (offset, player1RollCount) in rollCounts.enumerated() { + var u = universe + if u.player1.move(offset + minRoll) >= quantumMax { + player1Wins += universeCount * player1RollCount + continue + } + + for (offset, player2RollCount) in rollCounts.enumerated() { + var u2 = u + if u2.player2.move(offset + minRoll) >= quantumMax { + player2Wins += universeCount * player1RollCount * player2RollCount + continue + } + + newUniverses[u2, default: 0] += universeCount * player1RollCount * player2RollCount + } + } + } + + universes = newUniverses + } + + print("Part 2: ", max(player1Wins, player2Wins)) + } + + let quantumMax = 21 + + let minRoll = 3 + // 3 4 5 6 7 8 9 + let rollCounts = [1, 3, 6, 7, 6, 3, 1] + + struct Universe: Hashable { + var player1: Player + var player2: Player + } + + struct Player: Hashable { var position: Int var score: Int = 0 - mutating func move(_ roll: Int) -> Bool { + mutating func move(_ roll: Int) -> Int { position = 1 + (position + roll - 1) % 10 score += position - return score >= 1000 + return score } } struct Die { - var rolls = 0 - var nextRoll = 1 + var rolls = 0 + var nextRoll = 1 - mutating func roll() -> Int { - defer { - rolls += 1 - nextRoll += 1 + mutating func roll() -> Int { + defer { + rolls += 1 + nextRoll += 1 + } + + return nextRoll } - return nextRoll - } - - mutating func roll3() -> Int { - roll() + roll() + roll() - } + mutating func roll3() -> Int { + roll() + roll() + roll() + } } }