package main import "fmt" type game struct { turn, lastNumber int history map[int]int } func newGame(startingNumbers []int) *game { g := game{0, 0, map[int]int{}} for _, n := range startingNumbers { g.history[g.lastNumber] = g.turn g.turn++ g.lastNumber = n } return &g } func (g *game) takeTurn() (int, int) { // fmt.Printf("> Starting turn %d. last: %d\n", g.turn+1, g.lastNumber) // fmt.Printf(">> state %+v\n", g) var number int // Get the new number if t, ok := g.history[g.lastNumber]; ok { // fmt.Printf(">> We've seen %d before!\n", g.lastNumber) // Last number was seen number = g.turn - t } else { // Otherwise the number is zero number = 0 } // Store the last turn in history g.history[g.lastNumber] = g.turn // Go to the next turn g.turn++ g.lastNumber = number // fmt.Printf(">> Incrementing turn and updating state %+v\n", g) // fmt.Printf("Turn %d spoke \"%d\"\n", g.turn, g.lastNumber) return g.turn, g.lastNumber } func (g *game) turnTo(targetTurn int) int { var n int for g.turn < targetTurn { _, n = g.takeTurn() } return n } func part1() { numbers := []int{16, 12, 1, 0, 15, 7, 11} // numbers := []int{0, 3, 6} g := newGame(numbers) fmt.Println(g) t, n := g.takeTurn() for t < 2020 { t, n = g.takeTurn() } fmt.Printf("Part 1: Number on turn %d is %d\n", t, n) } func part2() { numbers := []int{16, 12, 1, 0, 15, 7, 11} // numbers := []int{0, 3, 6} g := newGame(numbers) fmt.Println(g) t, n := g.takeTurn() for t < 30000000 { t, n = g.takeTurn() } fmt.Printf("Part 2: Number on turn %d is %d\n", t, n) } func main() { fmt.Println(newGame([]int{16, 12, 1, 0, 15, 7, 11}).turnTo(2020)) fmt.Println(newGame([]int{16, 12, 1, 0, 15, 7, 11}).turnTo(30000000)) part1() part2() }