Решение на Game of Life от Ангел Ангелов

Обратно към всички решения

Към профила на Ангел Ангелов

Резултати

  • 10 точки от тестове
  • 1 отнета точка
  • 9 точки общо
  • 14 успешни тест(а)
  • 0 неуспешни тест(а)

Код

package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"strconv"
)
type GameOfLifeHandler struct {
game *GameOfLife
handler *http.ServeMux
}
func NewGameOfLifeHandler(cells [][2]int64) *GameOfLifeHandler {
g := &GameOfLifeHandler{}
g.game = NewGameOfLife()
for _, cell := range cells {
g.game.SpawnAt(cell[0], cell[1])
}
g.handler = http.NewServeMux()
g.handler.HandleFunc("/cell/status/", func(w http.ResponseWriter, req *http.Request) {
if req.Method != "GET" {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
req.ParseForm()
x, err := strconv.ParseInt(req.Form.Get("x"), 10, 64)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "%s", err)
}
y, err := strconv.ParseInt(req.Form.Get("y"), 10, 64)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "%s", err)
return
}
data, err := json.Marshal(map[string]bool{
"alive": g.game.AliveAt(x, y),
})
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "%s", err)
return
}
w.Write(data)
})
g.handler.HandleFunc("/generation/", func(w http.ResponseWriter, req *http.Request) {
if req.Method != "GET" {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
data, err := json.Marshal(map[string]interface{}{
"generation": g.game.Generation,
"living": g.game.Alive(),
})
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "%s", err)
return
}
w.Write(data)
})
g.handler.HandleFunc("/generation/evolve/", func(w http.ResponseWriter, req *http.Request) {
if req.Method != "POST" {
fmt.Fprintf(os.Stderr, "wrong method: %s\n", req.Method)
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
g.game.Evolve()
w.WriteHeader(http.StatusNoContent)
})
g.handler.HandleFunc("/reset/", func(w http.ResponseWriter, req *http.Request) {
if req.Method != "POST" {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
g.game.BigBang()
w.WriteHeader(http.StatusNoContent)
})
g.handler.HandleFunc("/cells/", func(w http.ResponseWriter, req *http.Request) {
if req.Method != "POST" {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
data, err := ioutil.ReadAll(req.Body)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "%s", err)
return
}
cells := make([]struct {
X int64 `json:"x"`
Y int64 `json:"y"`
}, 0)
err = json.Unmarshal(data, &cells)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "%s", err)
return
}
for _, cell := range cells {
g.game.SpawnAt(cell.X, cell.Y)
}
w.WriteHeader(http.StatusCreated)
})
return g
}
func (g *GameOfLifeHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
g.handler.ServeHTTP(w, req)
}
type GameOfLife struct {
board map[[2]int64]struct{}
Generation int
}
func NewGameOfLife() *GameOfLife {
g := &GameOfLife{}
g.BigBang()
return g
}
func (g *GameOfLife) AliveAt(x, y int64) bool {
_, ok := g.board[[2]int64{x, y}]
return ok
}
func (g *GameOfLife) Alive() [][2]int64 {
cells := make([][2]int64, len(g.board))
i := 0
for cell := range g.board {
cells[i] = cell
i++
}
return cells
}
func (g *GameOfLife) SpawnAt(x, y int64) {
g.board[[2]int64{x, y}] = struct{}{}
}
func (g *GameOfLife) BigBang() {
g.board = make(map[[2]int64]struct{})
g.Generation = 0
}
func (g *GameOfLife) Evolve() {
newBoard := make(map[[2]int64]struct{})
for cell := range g.board {
if g.cellWillSpawn(cell[0], cell[1]) {
newBoard[cell] = struct{}{}
}
for _, neighbour := range neighbours(cell[0], cell[1]) {
if g.cellWillSpawn(neighbour[0], neighbour[1]) {
newBoard[neighbour] = struct{}{}
}
}
}
g.board = newBoard
g.Generation++
}
func (g *GameOfLife) cellWillSpawn(x, y int64) bool {
aliveNeighbours := 0
for _, neighbour := range neighbours(x, y) {
if g.AliveAt(neighbour[0], neighbour[1]) {
aliveNeighbours++
}
}
if g.AliveAt(x, y) {
if aliveNeighbours < 2 {
return false // underpopulation
}
if aliveNeighbours > 3 {
return false // overpopulation
}
return true
} else {
if aliveNeighbours == 3 {
return true
}
return false
}
}
func neighbours(x, y int64) [][2]int64 {
return [][2]int64{
{x - 1, y},
{x, y - 1},
{x + 1, y},
{x, y + 1},
{x + 1, y + 1},
{x - 1, y - 1},
{x + 1, y - 1},
{x - 1, y + 1},
}
}

Лог от изпълнението

PASS
ok  	_/tmp/d20160126-5892-apfpee	0.005s
PASS
ok  	_/tmp/d20160126-5892-apfpee	0.007s
PASS
ok  	_/tmp/d20160126-5892-apfpee	0.006s
PASS
ok  	_/tmp/d20160126-5892-apfpee	0.007s
PASS
ok  	_/tmp/d20160126-5892-apfpee	0.006s
PASS
ok  	_/tmp/d20160126-5892-apfpee	0.007s
PASS
ok  	_/tmp/d20160126-5892-apfpee	0.007s
wrong method: GET
wrong method: PUT
wrong method: DELETE
PASS
ok  	_/tmp/d20160126-5892-apfpee	0.008s
PASS
ok  	_/tmp/d20160126-5892-apfpee	0.006s
PASS
ok  	_/tmp/d20160126-5892-apfpee	0.008s
PASS
ok  	_/tmp/d20160126-5892-apfpee	0.009s
PASS
ok  	_/tmp/d20160126-5892-apfpee	0.009s
PASS
ok  	_/tmp/d20160126-5892-apfpee	0.011s
PASS
ok  	_/tmp/d20160126-5892-apfpee	0.062s

История (1 версия и 1 коментар)

Ангел обнови решението на 26.01.2016 14:46 (преди над 2 години)

+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "strconv"
+)
+
+type GameOfLifeHandler struct {
+ game *GameOfLife
+ handler *http.ServeMux
+}
+
+func NewGameOfLifeHandler(cells [][2]int64) *GameOfLifeHandler {
+ g := &GameOfLifeHandler{}
+
+ g.game = NewGameOfLife()
+ for _, cell := range cells {
+ g.game.SpawnAt(cell[0], cell[1])
+ }
+
+ g.handler = http.NewServeMux()
+
+ g.handler.HandleFunc("/cell/status/", func(w http.ResponseWriter, req *http.Request) {
+ if req.Method != "GET" {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+
+ req.ParseForm()
+ x, err := strconv.ParseInt(req.Form.Get("x"), 10, 64)
+ if err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintf(w, "%s", err)
+ }
+ y, err := strconv.ParseInt(req.Form.Get("y"), 10, 64)
+ if err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintf(w, "%s", err)
+ return
+ }
+ data, err := json.Marshal(map[string]bool{
+ "alive": g.game.AliveAt(x, y),
+ })
+ if err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintf(w, "%s", err)
+ return
+ }
+ w.Write(data)
+ })
+
+ g.handler.HandleFunc("/generation/", func(w http.ResponseWriter, req *http.Request) {
+ if req.Method != "GET" {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+
+ data, err := json.Marshal(map[string]interface{}{
+ "generation": g.game.Generation,
+ "living": g.game.Alive(),
+ })
+ if err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintf(w, "%s", err)
+ return
+ }
+ w.Write(data)
+ })
+
+ g.handler.HandleFunc("/generation/evolve/", func(w http.ResponseWriter, req *http.Request) {
+ if req.Method != "POST" {
+ fmt.Fprintf(os.Stderr, "wrong method: %s\n", req.Method)
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+
+ g.game.Evolve()
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ g.handler.HandleFunc("/reset/", func(w http.ResponseWriter, req *http.Request) {
+ if req.Method != "POST" {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+
+ g.game.BigBang()
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ g.handler.HandleFunc("/cells/", func(w http.ResponseWriter, req *http.Request) {
+ if req.Method != "POST" {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+
+ data, err := ioutil.ReadAll(req.Body)
+ if err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintf(w, "%s", err)
+ return
+ }
+
+ cells := make([]struct {
+ X int64 `json:"x"`
+ Y int64 `json:"y"`
+ }, 0)
+
+ err = json.Unmarshal(data, &cells)
+ if err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintf(w, "%s", err)
+ return
+ }
+
+ for _, cell := range cells {
+ g.game.SpawnAt(cell.X, cell.Y)
+ }
+
+ w.WriteHeader(http.StatusCreated)
+ })
+
+ return g
+}
+
+func (g *GameOfLifeHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ g.handler.ServeHTTP(w, req)
+}
+
+type GameOfLife struct {
+ board map[[2]int64]struct{}
+ Generation int
+}
+
+func NewGameOfLife() *GameOfLife {
+ g := &GameOfLife{}
+ g.BigBang()
+ return g
+}
+
+func (g *GameOfLife) AliveAt(x, y int64) bool {
+ _, ok := g.board[[2]int64{x, y}]
+ return ok
+}
+
+func (g *GameOfLife) Alive() [][2]int64 {
+ cells := make([][2]int64, len(g.board))
+ i := 0
+ for cell := range g.board {
+ cells[i] = cell
+ i++
+ }
+ return cells
+}
+
+func (g *GameOfLife) SpawnAt(x, y int64) {
+ g.board[[2]int64{x, y}] = struct{}{}
+}
+
+func (g *GameOfLife) BigBang() {
+ g.board = make(map[[2]int64]struct{})
+ g.Generation = 0
+}
+
+func (g *GameOfLife) Evolve() {
+ newBoard := make(map[[2]int64]struct{})
+
+ for cell := range g.board {
+ if g.cellWillSpawn(cell[0], cell[1]) {
+ newBoard[cell] = struct{}{}
+ }
+ for _, neighbour := range neighbours(cell[0], cell[1]) {
+ if g.cellWillSpawn(neighbour[0], neighbour[1]) {
+ newBoard[neighbour] = struct{}{}
+ }
+ }
+ }
+
+ g.board = newBoard
+ g.Generation++
+}
+
+func (g *GameOfLife) cellWillSpawn(x, y int64) bool {
+ aliveNeighbours := 0
+ for _, neighbour := range neighbours(x, y) {
+ if g.AliveAt(neighbour[0], neighbour[1]) {
+ aliveNeighbours++
+ }
+ }
+
+ if g.AliveAt(x, y) {
+ if aliveNeighbours < 2 {
+ return false // underpopulation
+ }
+ if aliveNeighbours > 3 {
+ return false // overpopulation
+ }
+ return true
+ } else {
+ if aliveNeighbours == 3 {
+ return true
+ }
+ return false
+ }
+}
+
+func neighbours(x, y int64) [][2]int64 {
+ return [][2]int64{
+ {x - 1, y},
+ {x, y - 1},
+ {x + 1, y},
+ {x, y + 1},
+ {x + 1, y + 1},
+ {x - 1, y - 1},
+ {x + 1, y - 1},
+ {x - 1, y + 1},
+ }
+}