Files
golsky/grid.go

125 lines
2.1 KiB
Go

package main
import (
"bufio"
"errors"
"fmt"
"os"
"strconv"
"strings"
"time"
)
type Grid struct {
Data [][]int
Width, Height int
}
// Create new empty grid and allocate Data according to provided dimensions
func NewGrid(width, height int) *Grid {
grid := &Grid{
Height: height,
Width: width,
Data: make([][]int, height),
}
for y := 0; y < height; y++ {
grid.Data[y] = make([]int, width)
}
return grid
}
func (grid *Grid) Clone() *Grid {
newgrid := &Grid{}
newgrid.Width = grid.Width
newgrid.Height = grid.Height
newgrid.Data = grid.Data
return newgrid
}
func GetFilename(generations int64) string {
now := time.Now()
return fmt.Sprintf("dump-%s-%d.gol", now.Format("20060102150405"), generations)
}
func (grid *Grid) SaveState(filename string) error {
file, err := os.Create(filename)
if err != nil {
return fmt.Errorf("failed to open state file: %w", err)
}
defer file.Close()
for y, _ := range grid.Data {
for _, cell := range grid.Data[y] {
_, err := file.WriteString(strconv.Itoa(cell))
if err != nil {
return fmt.Errorf("failed to write to state file: %w", err)
}
}
file.WriteString("\n")
}
return nil
}
func LoadState(filename string) (*Grid, error) {
fd, err := os.Open(filename)
if err != nil {
return nil, err
}
scanner := bufio.NewScanner(fd)
scanner.Split(bufio.ScanLines)
grid := &Grid{}
for scanner.Scan() {
items := strings.Split(scanner.Text(), "")
row := make([]int, len(items))
for idx, item := range items {
num, err := strconv.Atoi(item)
if err != nil {
return nil, err
}
if num > 1 {
return nil, errors.New("cells must be 0 or 1")
}
row[idx] = num
}
grid.Data = append(grid.Data, row)
}
// sanity check the grid
explen := 0
rows := 0
first := true
for _, row := range grid.Data {
length := len(row)
if first {
explen = length
first = false
}
if explen != length {
return nil, fmt.Errorf(fmt.Sprintf("all rows must be in the same length, got: %d, expected: %d",
length, explen))
}
rows++
}
grid.Width = explen
grid.Height = rows
return grid, nil
}