2021-12-21 10:53:36 +01:00
|
|
|
@main
|
|
|
|
struct Day21: Puzzle {
|
|
|
|
func run() {
|
|
|
|
part1()
|
2021-12-21 11:25:58 +01:00
|
|
|
part2()
|
2021-12-21 10:53:36 +01:00
|
|
|
}
|
2021-12-21 11:25:58 +01:00
|
|
|
let player1 = Player(position: 6)
|
|
|
|
let player2 = Player(position: 7)
|
2021-12-21 10:53:36 +01:00
|
|
|
|
|
|
|
func part1() {
|
|
|
|
var die = Die()
|
2021-12-21 11:25:58 +01:00
|
|
|
var player1 = player1
|
|
|
|
var player2 = player2
|
2021-12-21 10:53:36 +01:00
|
|
|
|
|
|
|
while true {
|
2021-12-21 11:25:58 +01:00
|
|
|
if player1.move(die.roll3()) >= 1000 {
|
2021-12-21 10:53:36 +01:00
|
|
|
print("Part 1: Player 1 won. ", die.rolls * player2.score)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2021-12-21 11:25:58 +01:00
|
|
|
if player2.move(die.roll3()) >= 1000 {
|
2021-12-21 10:53:36 +01:00
|
|
|
print("Part 1: Player 2 won. ", die.rolls * player1.score)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-21 11:25:58 +01:00
|
|
|
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 {
|
2021-12-21 10:53:36 +01:00
|
|
|
var position: Int
|
|
|
|
var score: Int = 0
|
|
|
|
|
2021-12-21 11:25:58 +01:00
|
|
|
mutating func move(_ roll: Int) -> Int {
|
2021-12-21 10:53:36 +01:00
|
|
|
position = 1 + (position + roll - 1) % 10
|
|
|
|
score += position
|
2021-12-21 11:25:58 +01:00
|
|
|
return score
|
2021-12-21 10:53:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Die {
|
|
|
|
|
2021-12-21 11:25:58 +01:00
|
|
|
var rolls = 0
|
|
|
|
var nextRoll = 1
|
2021-12-21 10:53:36 +01:00
|
|
|
|
2021-12-21 11:25:58 +01:00
|
|
|
mutating func roll() -> Int {
|
|
|
|
defer {
|
|
|
|
rolls += 1
|
|
|
|
nextRoll += 1
|
|
|
|
}
|
2021-12-21 10:53:36 +01:00
|
|
|
|
2021-12-21 11:25:58 +01:00
|
|
|
return nextRoll
|
|
|
|
}
|
2021-12-21 10:53:36 +01:00
|
|
|
|
2021-12-21 11:25:58 +01:00
|
|
|
mutating func roll3() -> Int {
|
|
|
|
roll() + roll() + roll()
|
|
|
|
}
|
2021-12-21 10:53:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|