Диана обнови решението на 26.01.2016 14:40 (преди над 2 години)
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "strconv"
+)
+
+type Cell struct {
+ X int64 `json:"x"`
+ Y int64 `json:"y"`
+}
+type GameOfLife struct {
+ cells map[[2]int64]struct{}
+ Generation int
+}
+
+func NewGameOflife(cells map[[2]int64]struct{}) *GameOfLife {
+ return &GameOfLife{cells: cells, Generation: 0}
+}
+
+func (g *GameOfLife) addCells(toAdd []Cell) {
+ for _, cell := range toAdd {
+ g.cells[[2]int64{cell.X, cell.Y}] = struct{}{}
+ }
+}
+
+func (g *GameOfLife) alive(x, y int64) bool {
+ cell := [2]int64{x, y}
+ _, ok := g.cells[cell]
+ return ok
+}
+
+func (g *GameOfLife) reset() {
+ g.cells = make(map[[2]int64]struct{})
+ g.Generation = 0
+}
+
+func (g *GameOfLife) countNeighbours(x, y int64) int {
+ neighbour := 0
+ var ok bool
+ if _, ok = g.cells[[2]int64{x - 1, y}]; ok {
+ neighbour += 1
+ }
+
+ if _, ok = g.cells[[2]int64{x, y - 1}]; ok {
+ neighbour += 1
+ }
+
+ if _, ok = g.cells[[2]int64{x + 1, y}]; ok {
+ neighbour += 1
+ }
+
+ if _, ok = g.cells[[2]int64{x, y + 1}]; ok {
+ neighbour += 1
+ }
+
+ if _, ok = g.cells[[2]int64{x + 1, y + 1}]; ok {
+ neighbour += 1
+ }
+
+ if _, ok = g.cells[[2]int64{x - 1, y - 1}]; ok {
+ neighbour += 1
+ }
+
+ if _, ok = g.cells[[2]int64{x + 1, y - 1}]; ok {
+ neighbour += 1
+ }
+
+ if _, ok = g.cells[[2]int64{x - 1, y + 1}]; ok {
+ neighbour += 1
+ }
+ return neighbour
+}
+
+func (g *GameOfLife) evolve() {
+ g.Generation += 1
+ var ok bool
+ evolved := make(map[[2]int64]struct{})
+ neighbour := 0
+ for cell := range g.cells {
+ neighbour = 0
+ if _, ok = g.cells[[2]int64{cell[0] - 1, cell[1]}]; ok {
+ neighbour += 1
+ } else {
+ if g.countNeighbours(cell[0]-1, cell[1]) == 3 {
+ evolved[[2]int64{cell[0] - 1, cell[1]}] = struct{}{}
+ }
+ }
+
+ if _, ok = g.cells[[2]int64{cell[0], cell[1] - 1}]; ok {
+ neighbour += 1
+ } else {
+ if g.countNeighbours(cell[0], cell[1]-1) == 3 {
+ evolved[[2]int64{cell[0], cell[1] - 1}] = struct{}{}
+ }
+ }
+
+ if _, ok = g.cells[[2]int64{cell[0] + 1, cell[1]}]; ok {
+ neighbour += 1
+ } else {
+ if g.countNeighbours(cell[0]+1, cell[1]) == 3 {
+ evolved[[2]int64{cell[0] + 1, cell[1]}] = struct{}{}
+ }
+ }
+
+ if _, ok = g.cells[[2]int64{cell[0], cell[1] + 1}]; ok {
+ neighbour += 1
+ } else {
+ if g.countNeighbours(cell[0], cell[1]+1) == 3 {
+ evolved[[2]int64{cell[0], cell[1] + 1}] = struct{}{}
+ }
+ }
+
+ if _, ok = g.cells[[2]int64{cell[0] + 1, cell[1] + 1}]; ok {
+ neighbour += 1
+ } else {
+ if g.countNeighbours(cell[0]+1, cell[1]+1) == 3 {
+ evolved[[2]int64{cell[0] + 1, cell[1] + 1}] = struct{}{}
+ }
+ }
+
+ if _, ok = g.cells[[2]int64{cell[0] - 1, cell[1] - 1}]; ok {
+ neighbour += 1
+ } else {
+ if g.countNeighbours(cell[0]-1, cell[1]-1) == 3 {
+ evolved[[2]int64{cell[0] - 1, cell[1] - 1}] = struct{}{}
+ }
+ }
+
+ if _, ok = g.cells[[2]int64{cell[0] + 1, cell[1] - 1}]; ok {
+ neighbour += 1
+ } else {
+ if g.countNeighbours(cell[0]+1, cell[1]-1) == 3 {
+ evolved[[2]int64{cell[0] + 1, cell[1] - 1}] = struct{}{}
+ }
+ }
+
+ if _, ok = g.cells[[2]int64{cell[0] - 1, cell[1] + 1}]; ok {
+ neighbour += 1
+ } else {
+ if g.countNeighbours(cell[0]-1, cell[1]+1) == 3 {
+ evolved[[2]int64{cell[0] - 1, cell[1] + 1}] = struct{}{}
+ }
+ }
+
+ if neighbour == 2 || neighbour == 3 {
+ evolved[cell] = struct{}{}
+ }
+
+ }
+ g.cells = evolved
+}
+
+func (g *GameOfLife) getLiving() [][2]int64 {
+ living := make([][2]int64, 0)
+ for cell := range g.cells {
+ living = append(living, cell)
+ }
+ return living
+}
+
+type GameOfLifeHandler struct {
+ cells *GameOfLife
+ handler *http.ServeMux
+}
+
+func NewGameOfLifeHandler(cells [][2]int64) *GameOfLifeHandler {
+ game := &GameOfLifeHandler{}
+ board := make(map[[2]int64]struct{})
+ for _, cell := range cells {
+ board[cell] = struct{}{}
+ }
+ game.cells = NewGameOflife(board)
+ game.handler = http.NewServeMux()
+
+ game.handler.HandleFunc("/cell/status/", game.getStatus)
+ game.handler.HandleFunc("/generation/", game.getLiving)
+ game.handler.HandleFunc("/reset/", game.reset)
+ game.handler.HandleFunc("/cells/", game.addCells)
+ game.handler.HandleFunc("/generation/evolve/", game.evolve)
+
+ return game
+}
+
+func (g *GameOfLifeHandler) addCells(w http.ResponseWriter, req *http.Request) {
+ if req.Method != "POST" {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+ body, err := ioutil.ReadAll(req.Body)
+ if err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintf(w, "%s Missing a", err)
+ return
+ }
+
+ newCells := make([]Cell, 0)
+ err = json.Unmarshal(body, &newCells)
+
+ if err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintf(w, "%s Unmarshal error", err)
+ return
+ }
+
+ g.cells.addCells(newCells)
+ w.WriteHeader(http.StatusCreated)
+}
+
+func (g *GameOfLifeHandler) evolve(w http.ResponseWriter, req *http.Request) {
+ if req.Method != "POST" {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+
+ g.cells.evolve()
+ w.WriteHeader(http.StatusNoContent)
+}
+
+func (g *GameOfLifeHandler) reset(w http.ResponseWriter, req *http.Request) {
+ if req.Method != "POST" {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+ g.cells.reset()
+ w.WriteHeader(http.StatusNoContent)
+}
+
+func (g *GameOfLifeHandler) getLiving(w http.ResponseWriter, req *http.Request) {
+ if req.Method != "GET" {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+ cells := g.cells.getLiving()
+
+ data, err := json.Marshal(map[string]interface{}{"generation": g.cells.Generation, "living": cells})
+ if err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintf(w, "%s Json error", err)
+ }
+ w.Write(data)
+}
+
+func (g *GameOfLifeHandler) getStatus(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 Missing argument:x", err)
+ }
+ y, err := strconv.ParseInt(req.Form.Get("y"), 10, 64)
+ if err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintf(w, "%s Missing argument:y", err)
+ }
+ alive := g.cells.alive(x, y)
+ data, err := json.Marshal(map[string]bool{"alive": alive})
+ if err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintf(w, "%s Json error", err)
+ }
+ w.Write(data)
+}
+
+func (g *GameOfLifeHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ g.handler.ServeHTTP(w, req)
+}
За съжаление имаш race condition при достъпа на cells
map-a ти. Тестовете не го хващат всеки път, за това аз ще ти махна една точка.