package main import ( "fmt" "log" "os" "strconv" ) var playerCount, marbleCount int var game *Game func main() { if len(os.Args) < 3 { fmt.Println("Usage: day09 <# players> <# marbles>") os.Exit(1) } playerCount, marbleCount = Atoi(os.Args[1]), Atoi(os.Args[2]) part1() } func part1() { g := NewGame(playerCount, marbleCount) for i := 1; i <= marbleCount; i++ { if i%23 == 0 { g.score(i) } else { g.insertMarble(&Marble{value: i}) } g.nextPlayer() } fmt.Println("* Winner *") g.printWinner() } type Game struct { playerCount, marbleCount int currentPlayer int scores map[int]int currentMarble *Marble } func NewGame(players, marbles int) *Game { startMarble := &Marble{ value: 0, } startMarble.clockwise = startMarble startMarble.widdershins = startMarble return &Game{ playerCount: players, marbleCount: marbles, currentPlayer: 1, scores: make(map[int]int), currentMarble: startMarble, } } func (g *Game) insertMarble(m *Marble) { m.clockwise = g.currentMarble.clockwise.clockwise m.widdershins = g.currentMarble.clockwise g.currentMarble.clockwise.clockwise.widdershins = m g.currentMarble.clockwise.clockwise = m g.currentMarble = m } func (g *Game) score(val int) { g.scores[g.currentPlayer] += val for i := 0; i < 6; i++ { g.currentMarble = g.currentMarble.widdershins } // Remove g.currentMarble.widdershins // adding it's value to the current player's score rem := g.currentMarble.widdershins g.currentMarble.widdershins = rem.widdershins g.currentMarble.widdershins.clockwise = g.currentMarble g.scores[g.currentPlayer] += rem.value } func (g *Game) nextPlayer() { if g.currentPlayer == g.playerCount { g.currentPlayer = 1 } else { g.currentPlayer++ } } func (g *Game) printState() { fmt.Printf("[%d] ", g.currentPlayer) p := *g.currentMarble for p.value != 0 { // Find the '0' marble p = *p.clockwise } if p.value == g.currentMarble.value { fmt.Printf("(%d)", p.value) } else { fmt.Printf(" %d ", p.value) } p = *p.clockwise for p.value != 0 { if p.value == g.currentMarble.value { fmt.Printf("(%d)", p.value) } else { fmt.Printf(" %d ", p.value) } p = *p.clockwise } fmt.Println("") } func (g *Game) printScores() { for i := 1; i <= g.playerCount; i++ { fmt.Println(i, ":", g.scores[i]) } } func (g *Game) printWinner() { var top int var winner int for k, v := range g.scores { if v > top { top = v winner = k } } fmt.Println(winner, ":", top) } type Marble struct { value int clockwise *Marble widdershins *Marble } func Atoi(i string) int { var ret int var err error if ret, err = strconv.Atoi(i); err != nil { log.Fatal("Invalid Atoi") } return ret }