Extracting and testing generation emit and checksumming bits
This commit is contained in:
parent
c0184dd9df
commit
353b59b303
@ -452,3 +452,31 @@ func TestGameStateCellsCanHaveTheirValueSet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGameOfLifeEmitsGenerationTicksUntilStasis(t *testing.T) {
|
||||||
|
game, err := newTestGameOfLife()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
genTicks, err := game.Generations()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
nGens := 0
|
||||||
|
|
||||||
|
for gen := range genTicks {
|
||||||
|
if gen.N > 3000 {
|
||||||
|
t.Errorf("%v is too many generations!", gen.N)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
nGens = gen.N
|
||||||
|
}
|
||||||
|
|
||||||
|
if nGens < 3 {
|
||||||
|
t.Errorf("%v is too few generations!", nGens)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -19,15 +19,6 @@ var (
|
|||||||
"Millisecond sleep interval per generation")
|
"Millisecond sleep interval per generation")
|
||||||
)
|
)
|
||||||
|
|
||||||
func pushChecksum(checksum string, checksums []string) {
|
|
||||||
head := make([]string, 3)
|
|
||||||
copy(head, checksums[:3])
|
|
||||||
checksums[0] = checksum
|
|
||||||
checksums[1] = head[0]
|
|
||||||
checksums[2] = head[1]
|
|
||||||
checksums[3] = head[2]
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
@ -38,52 +29,32 @@ func main() {
|
|||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
checksums := make([]string, 4)
|
genTicks, err := game.Generations()
|
||||||
checksums[0], checksums[1], checksums[2], checksums[3] = "foo", "bar", "baz", "qwx"
|
|
||||||
ck, err := game.Checksum()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "NAY NAY: %v\n", err)
|
fmt.Fprintf(os.Stderr, "No generations?: %v\n", err)
|
||||||
os.Exit(3)
|
os.Exit(3)
|
||||||
}
|
}
|
||||||
pushChecksum(ck, checksums)
|
|
||||||
|
|
||||||
ticks := time.Tick(time.Duration(*sleepMs) * time.Millisecond)
|
sleepInterval := time.Duration(*sleepMs * 1000 * 1000)
|
||||||
generations := 0
|
for genTick := range genTicks {
|
||||||
for now := range ticks {
|
fmt.Printf("\nGeneration %v\n%v\n", genTick.N, time.Now())
|
||||||
fmt.Printf("\nGeneration %v\n%v\n", generations, now)
|
|
||||||
fmt.Println(game)
|
fmt.Println(game)
|
||||||
|
|
||||||
game.EvaluateGeneration()
|
game.EvaluateGeneration()
|
||||||
|
|
||||||
curChecksum, err := game.Checksum()
|
if genTick.Error != nil {
|
||||||
if err != nil {
|
fmt.Fprintf(os.Stderr, "%s: %s\n", genTick.Message, genTick.Error)
|
||||||
fmt.Fprintf(os.Stderr, "Failed to calculate current game checksum: %v\n", err)
|
|
||||||
os.Exit(4)
|
os.Exit(4)
|
||||||
}
|
}
|
||||||
|
|
||||||
if checksums[0] == curChecksum || checksums[1] == curChecksum {
|
if len(genTick.Message) > 0 {
|
||||||
fmt.Println("Stasis!")
|
fmt.Println(genTick.Message)
|
||||||
os.Exit(0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if checksums[2] == curChecksum {
|
if *mutate && genTick.N%2 == 0 {
|
||||||
fmt.Println("Checksum found 2 periods ago")
|
|
||||||
fmt.Println("Stasis with 2-period oscillator(s)!")
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if checksums[3] == curChecksum {
|
|
||||||
fmt.Println("Checksum found 3 periods ago")
|
|
||||||
fmt.Println("Stasis with 3-period oscillator(s)!")
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
pushChecksum(curChecksum, checksums)
|
|
||||||
|
|
||||||
if *mutate && generations%2 == 0 {
|
|
||||||
game.Mutate()
|
game.Mutate()
|
||||||
}
|
}
|
||||||
|
|
||||||
generations++
|
time.Sleep(sleepInterval)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,3 +117,86 @@ func (game *GameOfLife) ImportRandomState() error {
|
|||||||
func (game *GameOfLife) String() string {
|
func (game *GameOfLife) String() string {
|
||||||
return fmt.Sprintf("%s\n", game.State)
|
return fmt.Sprintf("%s\n", game.State)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (game *GameOfLife) emitGenerations(genTicks chan *GenerationTick) {
|
||||||
|
defer close(genTicks)
|
||||||
|
n := 0
|
||||||
|
|
||||||
|
checksums := make([]string, 4)
|
||||||
|
checksums[0], checksums[1], checksums[2], checksums[3] = "foo", "bar", "baz", "qwx"
|
||||||
|
ck, err := game.Checksum()
|
||||||
|
if err != nil {
|
||||||
|
genTicks <- &GenerationTick{
|
||||||
|
N: n,
|
||||||
|
Error: err,
|
||||||
|
Message: "NAY NAY",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pushChecksum(ck, checksums)
|
||||||
|
|
||||||
|
for {
|
||||||
|
game.EvaluateGeneration()
|
||||||
|
|
||||||
|
curChecksum, err := game.Checksum()
|
||||||
|
if err != nil {
|
||||||
|
genTicks <- &GenerationTick{
|
||||||
|
N: n,
|
||||||
|
Error: err,
|
||||||
|
Message: "Failed to calculate current game checksum",
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if checksums[0] == curChecksum || checksums[1] == curChecksum {
|
||||||
|
genTicks <- &GenerationTick{
|
||||||
|
N: n,
|
||||||
|
Error: nil,
|
||||||
|
Message: "Stasis!",
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if checksums[2] == curChecksum {
|
||||||
|
genTicks <- &GenerationTick{
|
||||||
|
N: n,
|
||||||
|
Error: nil,
|
||||||
|
Message: "Stasis with 2-period oscillator(s)!",
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if checksums[3] == curChecksum {
|
||||||
|
genTicks <- &GenerationTick{
|
||||||
|
N: n,
|
||||||
|
Error: nil,
|
||||||
|
Message: "Stasis with 3-period oscillator(s)!",
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
pushChecksum(curChecksum, checksums)
|
||||||
|
|
||||||
|
genTicks <- &GenerationTick{
|
||||||
|
N: n,
|
||||||
|
Error: nil,
|
||||||
|
Message: "",
|
||||||
|
}
|
||||||
|
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (game *GameOfLife) Generations() (<-chan *GenerationTick, error) {
|
||||||
|
genTicks := make(chan *GenerationTick)
|
||||||
|
go game.emitGenerations(genTicks)
|
||||||
|
return (<-chan *GenerationTick)(genTicks), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func pushChecksum(checksum string, checksums []string) {
|
||||||
|
head := make([]string, 3)
|
||||||
|
copy(head, checksums[:3])
|
||||||
|
checksums[0] = checksum
|
||||||
|
checksums[1] = head[0]
|
||||||
|
checksums[2] = head[1]
|
||||||
|
checksums[3] = head[2]
|
||||||
|
}
|
||||||
|
7
conway/generation_tick.go
Normal file
7
conway/generation_tick.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package conway
|
||||||
|
|
||||||
|
type GenerationTick struct {
|
||||||
|
N int
|
||||||
|
Error error
|
||||||
|
Message string
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user