Решение на Game of Life от Даниел Тасков

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

Към профила на Даниел Тасков

Резултати

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

Код

package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strconv"
"sync"
)
type empty struct{}
type pair [2]int64
type GameOfLifeHandler struct {
alive map[pair]empty
gen int64
*http.ServeMux
*sync.Mutex
}
type cellStatusS struct {
Alive bool `json:"alive"`
}
type generationS struct {
Generation int64 `json:"generation"`
Living []pair `json:"living"`
}
type cellsS struct {
Cells []struct {
X int64 `json:"x"`
Y int64 `json:"y"`
}
}
func NewGameOfLifeHandler(cells [][2]int64) *GameOfLifeHandler {
golh := &GameOfLifeHandler{map[pair]empty{}, 0, http.NewServeMux(), &sync.Mutex{}}
for _, v := range cells {
golh.alive[v] = empty{}
}
golh.HandleFunc("/cell/status/", func(rw http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if r.Method == "GET" {
q := r.URL.Query()
x, errx := strconv.ParseInt(q["x"][0], 10, 64)
y, erry := strconv.ParseInt(q["y"][0], 10, 64)
if errx != nil || erry != nil {
rw.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(rw, "'x' and 'y' should be int64s")
return
}
rw.WriteHeader(http.StatusOK)
res, _ := json.Marshal(golh.getCellStatus(x, y))
fmt.Fprintf(rw, "%s", res)
} else {
rw.WriteHeader(http.StatusMethodNotAllowed)
}
})
golh.HandleFunc("/generation/", func(rw http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if r.Method == "GET" {
rw.WriteHeader(http.StatusOK)
res, _ := json.Marshal(golh.getGeneration())
fmt.Fprintf(rw, "%s", res)
} else {
rw.WriteHeader(http.StatusMethodNotAllowed)
}
})
golh.HandleFunc("/cells/", func(rw http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if r.Method == "POST" {
var cells cellsS
contents, err := ioutil.ReadAll(r.Body)
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(rw, "I failed with reading the request's body")
return
}
err = json.Unmarshal(contents, &cells)
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(rw, "Malformed json was passed")
return
}
var cellsSlice []pair
for _, v := range cells.Cells {
cellsSlice = append(cellsSlice, pair{v.X, v.Y})
}
golh.postCells(cellsSlice)
rw.WriteHeader(http.StatusNoContent)
} else {
rw.WriteHeader(http.StatusMethodNotAllowed)
}
})
golh.HandleFunc("/generation/evolve/", func(rw http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if r.Method == "POST" {
golh.postGenerationEvolve()
rw.WriteHeader(http.StatusNoContent)
} else {
rw.WriteHeader(http.StatusMethodNotAllowed)
}
})
golh.HandleFunc("/reset/", func(rw http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if r.Method == "POST" {
golh.postReset()
rw.WriteHeader(http.StatusNoContent)
} else {
rw.WriteHeader(http.StatusMethodNotAllowed)
}
})
return golh
}
func (g *GameOfLifeHandler) getCellStatus(x int64, y int64) cellStatusS {
g.Lock()
defer g.Unlock()
_, ok := g.alive[pair{x, y}]
return cellStatusS{ok}
}
func (g *GameOfLifeHandler) getGeneration() generationS {
g.Lock()
defer g.Unlock()
var cells []pair
for k, _ := range g.alive {
cells = append(cells, k)
}
return generationS{g.gen, cells}
}
func (g *GameOfLifeHandler) postCells(cells []pair) {
g.Lock()
defer g.Unlock()
for _, i := range cells {
if _, ok := g.alive[i]; !ok {
g.alive[i] = empty{}
}
}
}
func (g *GameOfLifeHandler) postGenerationEvolve() {
g.Lock()
defer g.Unlock()
alive1 := map[pair]empty{}
for k, _ := range g.alive {
alive1[k] = empty{}
}
g.gen++
cells := g.significantCells()
for k, _ := range cells {
n := g.neighbours(k[0], k[1])
if _, ok := g.alive[k]; (ok && n == 2) || n == 3 {
alive1[k] = empty{}
} else {
delete(alive1, k)
}
}
g.alive = alive1
}
var nes = [...]pair{{-1, -1}, {-1, 0}, {-1, 1},
{0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}
func (g *GameOfLifeHandler) significantCells() map[pair]empty {
cells := map[pair]empty{}
for k, _ := range g.alive {
cells[k] = empty{}
for _, v := range nes {
cells[pair{k[0] + v[0], k[1] + v[1]}] = empty{}
}
}
return cells
}
func (g *GameOfLifeHandler) neighbours(x int64, y int64) int8 {
count := int8(0)
for _, v := range nes {
if _, ok := g.alive[pair{x + v[0], y + v[1]}]; ok {
count++
}
}
return count
}
func (g *GameOfLifeHandler) postReset() {
g.Lock()
defer g.Unlock()
g.alive = map[pair]empty{}
g.gen = 0
}

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

PASS
ok  	_/tmp/d20160126-5892-zsvoyj	0.005s
PASS
ok  	_/tmp/d20160126-5892-zsvoyj	0.005s
PASS
ok  	_/tmp/d20160126-5892-zsvoyj	0.006s
PASS
ok  	_/tmp/d20160126-5892-zsvoyj	0.007s
PASS
ok  	_/tmp/d20160126-5892-zsvoyj	0.006s
PASS
ok  	_/tmp/d20160126-5892-zsvoyj	0.006s
--- FAIL: TestAddingCells (0.00s)
	solution_test.go:225: Expected status Created but it was 400 with response: Malformed json was passed
	solution_test.go:235: Expected 7 living cells but they were 5
	solution_test.go:251: Added cells were not found in the living: [[0 2] [-1 2] [0 0] [1 1] [1 2]]
FAIL
exit status 1
FAIL	_/tmp/d20160126-5892-zsvoyj	0.006s
PASS
ok  	_/tmp/d20160126-5892-zsvoyj	0.009s
PASS
ok  	_/tmp/d20160126-5892-zsvoyj	0.007s
PASS
ok  	_/tmp/d20160126-5892-zsvoyj	0.008s
PASS
ok  	_/tmp/d20160126-5892-zsvoyj	0.009s
PASS
ok  	_/tmp/d20160126-5892-zsvoyj	0.009s
PASS
ok  	_/tmp/d20160126-5892-zsvoyj	0.011s
PASS
ok  	_/tmp/d20160126-5892-zsvoyj	0.201s

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

Даниел обнови решението на 21.01.2016 00:02 (преди над 2 години)

+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "strconv"
+)
+
+type empty struct{}
+type pair [2]int64
+
+type GameOfLifeHandler struct {
+ alive map[pair]empty
+ gen int64
+ *http.ServeMux
+}
+
+type cellStatusS struct {
+ Alive bool `json:"alive"`
+}
+
+type generationS struct {
+ Generation int64 `json:"generation"`
+ Living []pair `json:"living"`
+}
+
+type cellsS struct {
+ Cells []struct {
+ X int64 `json:"x"`
+ Y int64 `json:"y"`
+ }
+}
+
+func NewGameOfLifeHandler(cells [][2]int64) *GameOfLifeHandler {
+ golh := &GameOfLifeHandler{map[pair]empty{}, 0, http.NewServeMux()}
+
+ for _, v := range cells {
+ golh.alive[v] = empty{}
+ }
+
+ golh.HandleFunc("/cell/status/", func(rw http.ResponseWriter, r *http.Request) {
+ defer r.Body.Close()
+ if r.Method == "GET" {
+ q := r.URL.Query()
+ x, errx := strconv.ParseInt(q["x"][0], 10, 64)
+ y, erry := strconv.ParseInt(q["y"][0], 10, 64)
+ if errx != nil || erry != nil {
+ rw.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintf(rw, "'x' and 'y' should be int64s")
+ return
+ }
+ rw.WriteHeader(http.StatusOK)
+ res, _ := json.Marshal(golh.getCellStatus(x, y))
+ fmt.Fprintf(rw, "%s", res)
+ } else {
+ rw.WriteHeader(http.StatusMethodNotAllowed)
+ }
+ })
+ golh.HandleFunc("/generation/", func(rw http.ResponseWriter, r *http.Request) {
+ defer r.Body.Close()
+ if r.Method == "GET" {
+ rw.WriteHeader(http.StatusOK)
+ res, _ := json.Marshal(golh.getGeneration())
+ fmt.Fprintf(rw, "%s", res)
+ } else {
+ rw.WriteHeader(http.StatusMethodNotAllowed)
+ }
+ })
+ golh.HandleFunc("/cells/", func(rw http.ResponseWriter, r *http.Request) {
+ defer r.Body.Close()
+ if r.Method == "POST" {
+ var cells cellsS
+ contents, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ rw.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintf(rw, "I failed with reading the request's body")
+ return
+ }
+ err = json.Unmarshal(contents, &cells)
+ if err != nil {
+ rw.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintf(rw, "Malformed json was passed")
+ return
+ }
+ var cellsSlice []pair
+ for _, v := range cells.Cells {
+ cellsSlice = append(cellsSlice, pair{v.X, v.Y})
+ }
+ golh.postCells(cellsSlice)
+ rw.WriteHeader(http.StatusNoContent)
+ } else {
+ rw.WriteHeader(http.StatusMethodNotAllowed)
+ }
+ })
+ golh.HandleFunc("/generation/evolve/", func(rw http.ResponseWriter, r *http.Request) {
+ defer r.Body.Close()
+ if r.Method == "POST" {
+ golh.postGenerationEvolve()
+ rw.WriteHeader(http.StatusNoContent)
+ } else {
+ rw.WriteHeader(http.StatusMethodNotAllowed)
+ }
+ })
+ golh.HandleFunc("/reset/", func(rw http.ResponseWriter, r *http.Request) {
+ defer r.Body.Close()
+ if r.Method == "POST" {
+ golh.postReset()
+ rw.WriteHeader(http.StatusNoContent)
+ } else {
+ rw.WriteHeader(http.StatusMethodNotAllowed)
+ }
+ })
+
+ return golh
+}
+
+func (g *GameOfLifeHandler) getCellStatus(x int64, y int64) cellStatusS {
+ _, ok := g.alive[pair{x, y}]
+ return cellStatusS{ok}
+}
+
+func (g *GameOfLifeHandler) getGeneration() generationS {
+ var cells []pair
+ for k, _ := range g.alive {
+ cells = append(cells, k)
+ }
+ return generationS{g.gen, cells}
+}
+
+func (g *GameOfLifeHandler) postCells(cells []pair) {
+ for _, i := range cells {
+ if _, ok := g.alive[i]; !ok {
+ g.alive[i] = empty{}
+ }
+ }
+}
+
+func (g *GameOfLifeHandler) postGenerationEvolve() {
+ g.gen++
+ cells := g.significantCells()
+
+ for k, _ := range cells {
+ n := g.neighbours(k[0], k[1])
+ if _, ok := g.alive[k]; (ok && n == 2) || n == 3 {
+ g.alive[k] = empty{}
+ } else {
+ delete(g.alive, k)
+ }
+ }
+}
+
+var nes = [...]pair{{-1, -1}, {-1, 0}, {-1, 1},
+ {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}
+
+func (g *GameOfLifeHandler) significantCells() map[pair]empty {
+ cells := g.alive
+ for k, _ := range g.alive {
+ for _, v := range nes {
+ cells[pair{k[0] + v[0], k[1] + v[1]}] = empty{}
+ }
+ }
+ return cells
+}
+
+func (g *GameOfLifeHandler) neighbours(x int64, y int64) int8 {
+ count := int8(0)
+ for _, v := range nes {
+ if _, ok := g.alive[pair{x + v[0], y + v[1]}]; ok {
+ count++
+ }
+ }
+ return count
+}
+
+func (g *GameOfLifeHandler) postReset() {
+ g.alive = map[pair]empty{}
+ g.gen = 0
+}

Мого хубаво решение. Особено ми харесва type empty struct{}. Мисля, че можеш да го направиш още по - добро ако го пробваш с конкурентни кънекции за различни endpoint-и. Знай, че go HTTP сървърите правят отделна goroutine-а за всяка кънекция. Това, потенциално, е отделна нишка.

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

package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strconv"
+ "sync"
)
type empty struct{}
type pair [2]int64
type GameOfLifeHandler struct {
alive map[pair]empty
gen int64
*http.ServeMux
+ *sync.Mutex
}
type cellStatusS struct {
Alive bool `json:"alive"`
}
type generationS struct {
Generation int64 `json:"generation"`
Living []pair `json:"living"`
}
type cellsS struct {
Cells []struct {
X int64 `json:"x"`
Y int64 `json:"y"`
}
}
func NewGameOfLifeHandler(cells [][2]int64) *GameOfLifeHandler {
- golh := &GameOfLifeHandler{map[pair]empty{}, 0, http.NewServeMux()}
+ golh := &GameOfLifeHandler{map[pair]empty{}, 0, http.NewServeMux(), &sync.Mutex{}}
for _, v := range cells {
golh.alive[v] = empty{}
}
golh.HandleFunc("/cell/status/", func(rw http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if r.Method == "GET" {
q := r.URL.Query()
x, errx := strconv.ParseInt(q["x"][0], 10, 64)
y, erry := strconv.ParseInt(q["y"][0], 10, 64)
if errx != nil || erry != nil {
rw.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(rw, "'x' and 'y' should be int64s")
return
}
rw.WriteHeader(http.StatusOK)
res, _ := json.Marshal(golh.getCellStatus(x, y))
fmt.Fprintf(rw, "%s", res)
} else {
rw.WriteHeader(http.StatusMethodNotAllowed)
}
})
golh.HandleFunc("/generation/", func(rw http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if r.Method == "GET" {
rw.WriteHeader(http.StatusOK)
res, _ := json.Marshal(golh.getGeneration())
fmt.Fprintf(rw, "%s", res)
} else {
rw.WriteHeader(http.StatusMethodNotAllowed)
}
})
golh.HandleFunc("/cells/", func(rw http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if r.Method == "POST" {
var cells cellsS
contents, err := ioutil.ReadAll(r.Body)
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(rw, "I failed with reading the request's body")
return
}
err = json.Unmarshal(contents, &cells)
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(rw, "Malformed json was passed")
return
}
var cellsSlice []pair
for _, v := range cells.Cells {
cellsSlice = append(cellsSlice, pair{v.X, v.Y})
}
golh.postCells(cellsSlice)
rw.WriteHeader(http.StatusNoContent)
} else {
rw.WriteHeader(http.StatusMethodNotAllowed)
}
})
golh.HandleFunc("/generation/evolve/", func(rw http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if r.Method == "POST" {
golh.postGenerationEvolve()
rw.WriteHeader(http.StatusNoContent)
} else {
rw.WriteHeader(http.StatusMethodNotAllowed)
}
})
golh.HandleFunc("/reset/", func(rw http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if r.Method == "POST" {
golh.postReset()
rw.WriteHeader(http.StatusNoContent)
} else {
rw.WriteHeader(http.StatusMethodNotAllowed)
}
})
return golh
}
func (g *GameOfLifeHandler) getCellStatus(x int64, y int64) cellStatusS {
+ g.Lock()
+ defer g.Unlock()
_, ok := g.alive[pair{x, y}]
return cellStatusS{ok}
}
func (g *GameOfLifeHandler) getGeneration() generationS {
+ g.Lock()
+ defer g.Unlock()
var cells []pair
for k, _ := range g.alive {
cells = append(cells, k)
}
return generationS{g.gen, cells}
}
func (g *GameOfLifeHandler) postCells(cells []pair) {
+ g.Lock()
+ defer g.Unlock()
for _, i := range cells {
if _, ok := g.alive[i]; !ok {
g.alive[i] = empty{}
}
}
}
func (g *GameOfLifeHandler) postGenerationEvolve() {
+ g.Lock()
+ defer g.Unlock()
g.gen++
cells := g.significantCells()
-
for k, _ := range cells {
n := g.neighbours(k[0], k[1])
if _, ok := g.alive[k]; (ok && n == 2) || n == 3 {
g.alive[k] = empty{}
} else {
delete(g.alive, k)
}
}
+ fmt.Printf("alive: %+v", g.alive)
}
var nes = [...]pair{{-1, -1}, {-1, 0}, {-1, 1},
{0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}
func (g *GameOfLifeHandler) significantCells() map[pair]empty {
- cells := g.alive
+ cells := map[pair]empty{}
+
+ for k, v := range g.alive {
+ cells[k] = v
+ }
for k, _ := range g.alive {
for _, v := range nes {
cells[pair{k[0] + v[0], k[1] + v[1]}] = empty{}
}
}
return cells
}
func (g *GameOfLifeHandler) neighbours(x int64, y int64) int8 {
count := int8(0)
for _, v := range nes {
if _, ok := g.alive[pair{x + v[0], y + v[1]}]; ok {
count++
}
}
return count
}
func (g *GameOfLifeHandler) postReset() {
+ g.Lock()
+ defer g.Unlock()
g.alive = map[pair]empty{}
g.gen = 0
}

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

package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strconv"
"sync"
)
type empty struct{}
type pair [2]int64
type GameOfLifeHandler struct {
alive map[pair]empty
gen int64
*http.ServeMux
*sync.Mutex
}
type cellStatusS struct {
Alive bool `json:"alive"`
}
type generationS struct {
Generation int64 `json:"generation"`
Living []pair `json:"living"`
}
type cellsS struct {
Cells []struct {
X int64 `json:"x"`
Y int64 `json:"y"`
}
}
func NewGameOfLifeHandler(cells [][2]int64) *GameOfLifeHandler {
golh := &GameOfLifeHandler{map[pair]empty{}, 0, http.NewServeMux(), &sync.Mutex{}}
for _, v := range cells {
golh.alive[v] = empty{}
}
golh.HandleFunc("/cell/status/", func(rw http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if r.Method == "GET" {
q := r.URL.Query()
x, errx := strconv.ParseInt(q["x"][0], 10, 64)
y, erry := strconv.ParseInt(q["y"][0], 10, 64)
if errx != nil || erry != nil {
rw.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(rw, "'x' and 'y' should be int64s")
return
}
rw.WriteHeader(http.StatusOK)
res, _ := json.Marshal(golh.getCellStatus(x, y))
fmt.Fprintf(rw, "%s", res)
} else {
rw.WriteHeader(http.StatusMethodNotAllowed)
}
})
golh.HandleFunc("/generation/", func(rw http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if r.Method == "GET" {
rw.WriteHeader(http.StatusOK)
res, _ := json.Marshal(golh.getGeneration())
fmt.Fprintf(rw, "%s", res)
} else {
rw.WriteHeader(http.StatusMethodNotAllowed)
}
})
golh.HandleFunc("/cells/", func(rw http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if r.Method == "POST" {
var cells cellsS
contents, err := ioutil.ReadAll(r.Body)
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(rw, "I failed with reading the request's body")
return
}
err = json.Unmarshal(contents, &cells)
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(rw, "Malformed json was passed")
return
}
var cellsSlice []pair
for _, v := range cells.Cells {
cellsSlice = append(cellsSlice, pair{v.X, v.Y})
}
golh.postCells(cellsSlice)
rw.WriteHeader(http.StatusNoContent)
} else {
rw.WriteHeader(http.StatusMethodNotAllowed)
}
})
golh.HandleFunc("/generation/evolve/", func(rw http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if r.Method == "POST" {
golh.postGenerationEvolve()
rw.WriteHeader(http.StatusNoContent)
} else {
rw.WriteHeader(http.StatusMethodNotAllowed)
}
})
golh.HandleFunc("/reset/", func(rw http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if r.Method == "POST" {
golh.postReset()
rw.WriteHeader(http.StatusNoContent)
} else {
rw.WriteHeader(http.StatusMethodNotAllowed)
}
})
return golh
}
func (g *GameOfLifeHandler) getCellStatus(x int64, y int64) cellStatusS {
g.Lock()
defer g.Unlock()
_, ok := g.alive[pair{x, y}]
return cellStatusS{ok}
}
func (g *GameOfLifeHandler) getGeneration() generationS {
g.Lock()
defer g.Unlock()
var cells []pair
for k, _ := range g.alive {
cells = append(cells, k)
}
return generationS{g.gen, cells}
}
func (g *GameOfLifeHandler) postCells(cells []pair) {
g.Lock()
defer g.Unlock()
for _, i := range cells {
if _, ok := g.alive[i]; !ok {
g.alive[i] = empty{}
}
}
}
func (g *GameOfLifeHandler) postGenerationEvolve() {
g.Lock()
defer g.Unlock()
+ alive1 := map[pair]empty{}
+ for k, _ := range g.alive {
+ alive1[k] = empty{}
+ }
g.gen++
cells := g.significantCells()
for k, _ := range cells {
n := g.neighbours(k[0], k[1])
if _, ok := g.alive[k]; (ok && n == 2) || n == 3 {
- g.alive[k] = empty{}
+ alive1[k] = empty{}
} else {
- delete(g.alive, k)
+ delete(alive1, k)
}
}
- fmt.Printf("alive: %+v", g.alive)
+ g.alive = alive1
}
var nes = [...]pair{{-1, -1}, {-1, 0}, {-1, 1},
{0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}
func (g *GameOfLifeHandler) significantCells() map[pair]empty {
cells := map[pair]empty{}
- for k, v := range g.alive {
- cells[k] = v
- }
for k, _ := range g.alive {
+ cells[k] = empty{}
for _, v := range nes {
cells[pair{k[0] + v[0], k[1] + v[1]}] = empty{}
}
}
return cells
}
func (g *GameOfLifeHandler) neighbours(x int64, y int64) int8 {
count := int8(0)
for _, v := range nes {
if _, ok := g.alive[pair{x + v[0], y + v[1]}]; ok {
count++
}
}
return count
}
func (g *GameOfLifeHandler) postReset() {
g.Lock()
defer g.Unlock()
g.alive = map[pair]empty{}
g.gen = 0
}