Skip to content

Commit fbd0c0d

Browse files
authored
day 15 2020
1 parent fb50261 commit fbd0c0d

File tree

3 files changed

+125
-2
lines changed

3 files changed

+125
-2
lines changed

2020/day15/day15.go

+71-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,76 @@
11
package day15
22

3-
import "fmt"
3+
import (
4+
"fmt"
5+
"strconv"
6+
"strings"
7+
)
48

59
func Run(lines []string) error {
6-
return fmt.Errorf("not yet implemented")
10+
splat := strings.Split(lines[0], ",")
11+
numbers := make([]int, 0, len(splat))
12+
for _, s := range splat {
13+
num, err := strconv.Atoi(s)
14+
if err != nil {
15+
return fmt.Errorf("invalid number '%s'", s)
16+
}
17+
numbers = append(numbers, num)
18+
}
19+
20+
game := NewGame()
21+
game.SpeakAll(numbers...)
22+
lastNumber := game.PlayTo(2020)
23+
24+
fmt.Println("Part 1:", lastNumber)
25+
26+
lastNumber = game.PlayTo(30000000)
27+
28+
fmt.Println("Part 2:", lastNumber)
29+
return nil
30+
}
31+
32+
type GameState struct {
33+
LastSpoken int
34+
TurnIndex int
35+
numbersSpoken map[int][]int
36+
}
37+
38+
func NewGame() GameState {
39+
return GameState{LastSpoken: 0, TurnIndex: 0, numbersSpoken: make(map[int][]int)}
40+
}
41+
42+
func (g *GameState) PlayTo(index int) int {
43+
for {
44+
number := g.TakeTurn()
45+
if g.TurnIndex == index {
46+
return number
47+
}
48+
}
49+
}
50+
51+
// TakeTurn takes a game turn and returns the number spoken in it
52+
func (g *GameState) TakeTurn() int {
53+
if spokenAt, ok := g.numbersSpoken[g.LastSpoken]; ok && len(spokenAt) > 1 {
54+
age := spokenAt[len(spokenAt)-1] - spokenAt[len(spokenAt)-2]
55+
g.Speak(age)
56+
} else {
57+
g.Speak(0)
58+
}
59+
return g.LastSpoken
60+
}
61+
62+
func (g *GameState) Speak(number int) {
63+
g.TurnIndex++
64+
g.LastSpoken = number
65+
if list, ok := g.numbersSpoken[number]; ok {
66+
g.numbersSpoken[number] = append(list, g.TurnIndex)
67+
} else {
68+
g.numbersSpoken[number] = []int{g.TurnIndex}
69+
}
70+
}
71+
72+
func (g *GameState) SpeakAll(numbers ...int) {
73+
for _, num := range numbers {
74+
g.Speak(num)
75+
}
776
}

2020/day15/day15_test.go

+53
Original file line numberDiff line numberDiff line change
@@ -1 +1,54 @@
11
package day15
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
)
8+
9+
func TestGame(t *testing.T) {
10+
game := NewGame()
11+
game.SpeakAll(0, 3, 6)
12+
require.Equal(t, 3, game.TurnIndex)
13+
14+
require.Equal(t, 0, game.TakeTurn())
15+
require.Equal(t, 4, game.TurnIndex)
16+
17+
require.Equal(t, 3, game.TakeTurn())
18+
require.Equal(t, 5, game.TurnIndex)
19+
20+
require.Equal(t, 3, game.TakeTurn())
21+
require.Equal(t, 6, game.TurnIndex)
22+
23+
require.Equal(t, 1, game.TakeTurn())
24+
require.Equal(t, 7, game.TurnIndex)
25+
26+
require.Equal(t, 0, game.TakeTurn())
27+
require.Equal(t, 8, game.TurnIndex)
28+
29+
require.Equal(t, 4, game.TakeTurn())
30+
require.Equal(t, 9, game.TurnIndex)
31+
32+
require.Equal(t, 0, game.TakeTurn())
33+
require.Equal(t, 10, game.TurnIndex)
34+
}
35+
36+
func TestExampleGames(t *testing.T) {
37+
require.Equal(t, 1, playGame([]int{1, 3, 2}, 2020))
38+
require.Equal(t, 10, playGame([]int{2, 1, 3}, 2020))
39+
require.Equal(t, 27, playGame([]int{1, 2, 3}, 2020))
40+
require.Equal(t, 78, playGame([]int{2, 3, 1}, 2020))
41+
require.Equal(t, 438, playGame([]int{3, 2, 1}, 2020))
42+
require.Equal(t, 1836, playGame([]int{3, 1, 2}, 2020))
43+
}
44+
45+
func TestExampleJumboGames(t *testing.T) {
46+
require.Equal(t, 175594, playGame([]int{0, 3, 6}, 30000000))
47+
}
48+
49+
func playGame(startingNumbers []int, to int) int {
50+
game := NewGame()
51+
game.SpeakAll(startingNumbers...)
52+
game.PlayTo(to)
53+
return game.LastSpoken
54+
}

2020/day15/input.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0,20,7,16,1,18,15

0 commit comments

Comments
 (0)