AoC2021/src/day21/day21.go
kspickermann 815ae0b7d5 Day21
2021-12-21 17:48:31 +01:00

142 lines
2.9 KiB
Go

package main
import "fmt"
type player struct {
position int
score int
roundsPlayed int
}
type game struct {
players [2]player
currentPlayer int
winner int
winscore int
}
func main() {
n := 6
player1 := player{8, 0, 0}
player2 := player{7, 0, 0}
part1(player1, player2, n)
part2(player1, player2)
}
func part2(player1 player, player2 player) {
diceResultMap := generateDiceResultMap()
gameMap := make(map[game]int64)
startGame := game{[2]player{player1, player2}, 0, -1, 21}
gameMap[startGame] = 1
for i := 0; i < 20; i++ {
tmpGameMap := make(map[game]int64)
for game, gameAmount := range gameMap {
if game.winner == -1 {
for diceResult1, diceResultAmount1 := range diceResultMap {
tmpGame := game
tmpGame.playOneRoung(diceResult1)
tmpGameMap[tmpGame] += gameAmount * diceResultAmount1
}
} else {
tmpGameMap[game] += gameAmount
}
}
gameMap = tmpGameMap
printGameMapInfos(gameMap)
fmt.Println()
}
}
func printGameMapInfos(gameMap map[game]int64) {
fmt.Println(len(gameMap))
var amountGames int64
var winnersPlayer1 int64
var winnersPlayer2 int64
var winSum int64
var bothWinners int64
var noWin int64
for key, val := range gameMap {
if key.winner == 0 {
winnersPlayer1 += val
winSum += val
}
if key.winner == 1 {
winnersPlayer2 += val
winSum += val
}
if key.winner == -1 {
noWin += val
}
amountGames += val
}
fmt.Printf("Amount Games: %d \n", amountGames)
fmt.Printf("Winners: %d \n", winSum)
fmt.Printf("Games Winner 1: %d \n", winnersPlayer1)
fmt.Printf("Games Winner 2: %d \n", winnersPlayer2)
fmt.Printf("Games No Win: %d \n", noWin)
fmt.Printf("Games Both Win: %d \n", bothWinners)
}
func (game *game) playOneRoung(increase int) {
if increasePlayer(&game.players[game.currentPlayer], increase, game.winscore) {
game.winner = game.currentPlayer
}
if game.currentPlayer == 1 {
game.currentPlayer = 0
} else {
game.currentPlayer = 1
}
}
func generateDiceResultMap() map[int]int64 {
tmpDiceResultMap := make(map[int]int64)
for a := 1; a < 4; a++ {
for b := 1; b < 4; b++ {
for c := 1; c < 4; c++ {
tmpDiceResultMap[a+b+c] += 1
}
}
}
return tmpDiceResultMap
}
func part1(player1 player, player2 player, n int) (diceRolls int) {
game := game{[2]player{player1, player2}, 0, -1, 1000}
for {
game.playOneRoung(n)
reduceN(&n, &diceRolls)
if game.winner != -1 {
fmt.Println(min(game.players[0].score, game.players[1].score) * diceRolls)
return
}
}
}
func reduceN(n *int, counter *int) {
*n--
if *n < 0 {
*n = 9
}
*counter += 3
}
func increasePlayer(player *player, n int, winscore int) bool {
(*player).position += n
if (*player).position > 10 {
(*player).position -= 10
}
(*player).score += (*player).position
(*player).roundsPlayed++
return (*player).score >= winscore
}
func min(a, b int) int {
if a < b {
return a
}
return b
}