Skip to content

Commit c69d1b0

Browse files
committed
Day 21 go
1 parent df89bc0 commit c69d1b0

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

2021/go/d21/main.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
type Player struct {
8+
pos, score int
9+
}
10+
11+
type State struct {
12+
totalRolls, prevRoll, prevRoll2 int
13+
players [2]Player
14+
}
15+
16+
// Advent of Code (AOC) 2021 Day 21 Dira Dice
17+
func main() {
18+
state := State{players: [2]Player{{pos: 8}, {pos: 6}}}
19+
for !state.gameOver(1000) {
20+
state = state.rollPracticeDice()
21+
}
22+
23+
losingScore := state.players[0].score
24+
if state.players[1].score < losingScore {
25+
losingScore = state.players[1].score
26+
}
27+
fmt.Printf("part 1: %v\n", losingScore*state.totalRolls)
28+
29+
state = State{players: [2]Player{{pos: 8}, {pos: 6}}}
30+
cache := map[State][2]int64{}
31+
res := playRecursiveUniverses(state, cache)
32+
33+
max := res[0]
34+
if res[1] > max {
35+
max = res[1]
36+
}
37+
38+
fmt.Printf("part 2: %v\n", max)
39+
}
40+
41+
// return number of wins as array player1, player2
42+
func playRecursiveUniverses(state State, cache map[State][2]int64) [2]int64 {
43+
res, ok := cache[state]
44+
if !ok {
45+
for i := 1; i <= 3; i++ { // play Dira Dice all faces 1,2,3 and count winners together
46+
lr := playRound(i, state, cache)
47+
res[0] += lr[0]
48+
res[1] += lr[1]
49+
}
50+
cache[state] = res
51+
}
52+
return res
53+
}
54+
55+
// return number of wins as array player1, player2
56+
func playRound(currentRoll int, state State, cache map[State][2]int64) [2]int64 {
57+
state = state.roll(currentRoll)
58+
59+
if state.gameOver(21) { // We have winner, return it as array 0,1 or 1,0
60+
res := [2]int64{0, 0}
61+
currentPlayer := (state.totalRolls / 3) % 2
62+
res[currentPlayer] = 1
63+
return res
64+
}
65+
return playRecursiveUniverses(state, cache)
66+
}
67+
68+
func (state State) gameOver(score int) bool {
69+
return state.players[0].score >= score || state.players[1].score >= score
70+
}
71+
72+
func (state State) rollPracticeDice() State {
73+
currentRoll := (state.totalRolls)%100 + 1
74+
return state.roll(currentRoll)
75+
}
76+
77+
func (state State) roll(currentRoll int) State {
78+
playerRollNumber := state.totalRolls % 3 // number of rolls for current player
79+
currentPlayer := (state.totalRolls / 3) % 2
80+
state.totalRolls += 1
81+
82+
if playerRollNumber == 2 {
83+
// third roll for the player, move it
84+
totalRollSum := currentRoll + state.prevRoll + state.prevRoll2 // rolls sum
85+
moved := state.players[currentPlayer].move(totalRollSum)
86+
state.players[currentPlayer] = moved
87+
}
88+
state.prevRoll, state.prevRoll2 = currentRoll, state.prevRoll
89+
return state
90+
}
91+
92+
func (p Player) move(move int) Player {
93+
pos := (p.pos+move-1)%10 + 1
94+
score := pos + p.score
95+
return Player{pos, score}
96+
}

0 commit comments

Comments
 (0)