adventofcode/2018/day09/day09.go

144 lines
2.7 KiB
Go

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
}