-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgol.go
121 lines (100 loc) · 2.23 KB
/
gol.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package main
// Rules:
// Any live cell with fewer than two live neighbours dies, as if caused by underpopulation.
// Any live cell with two or three live neighbours lives on to the next generation.
// Any live cell with more than three live neighbours dies, as if by overpopulation.
// Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
type coord struct {
x, y int
}
func (c *coord) valid(size int) bool {
return c.x > -1 && c.y > -1 && c.x < size && c.y < size
}
type universe struct {
prev map[coord]struct{}
current map[coord]struct{}
Size int
}
func (u *universe) String() string {
s := ""
for row := 0; row < u.Size; row++ {
for col := 0; col < u.Size; col++ {
if _, alive := u.current[coord{row, col}]; alive {
s += " * "
} else {
s += " - "
}
}
s += "\n"
}
return s
}
func (u *universe) iterate() {
u.prev = make(map[coord]struct{})
for k := range u.current {
u.prev[k] = struct{}{}
}
u.current = make(map[coord]struct{})
var aliveN int
for row := 0; row < u.Size; row++ {
for col := 0; col < u.Size; col++ {
c := coord{row, col}
aliveN, _ = u.neighbours(c.x, c.y)
if _, alive := u.prev[c]; alive {
if aliveN == 2 || aliveN == 3 {
u.current[c] = struct{}{}
}
} else {
if aliveN == 3 {
u.current[c] = struct{}{}
}
}
}
}
}
func (u *universe) neighbours(row, col int) (int, int) {
nCells := []coord{
{row - 1, col - 1}, {row - 1, col}, {row - 1, col + 1},
{row, col - 1}, {row, col + 1},
{row + 1, col - 1}, {row + 1, col}, {row + 1, col + 1},
}
var (
alive int
dead int
)
for i := range nCells {
if !nCells[i].valid(u.Size) {
continue
}
if _, present := u.prev[nCells[i]]; present {
alive++
} else {
dead++
}
}
return alive, dead
}
func (u *universe) delta() ([]coord, []coord) {
var (
live []coord
die []coord
)
for c := range u.current {
if _, alive := u.prev[c]; !alive {
live = append(live, c)
}
}
for c := range u.prev {
if _, alive := u.current[c]; !alive {
die = append(die, c)
}
}
return live, die
}
func newUniverse(size int) universe {
return universe{
prev: make(map[coord]struct{}),
current: make(map[coord]struct{}),
Size: size,
}
}