package main import ( "log" "math" "strings" "io/ioutil" h "git.bullercodeworks.com/brian/adventofcode/helpers" ) type Layout struct { Area map[h.Coordinate]bool BottomRight h.Coordinate History map[string]float64 } func NewLayout(filename string) *Layout { ret := Layout{ Area: make(map[h.Coordinate]bool), BottomRight: h.Coordinate{X: 0, Y: 0}, History: make(map[string]float64), } input, err := ioutil.ReadFile(filename) if err != nil { log.Fatal(err.Error()) } lines := make([]string, 0) for _, line := range strings.Split(string(input), "\n") { lines = append(lines, line) } for y := 0; y < len(lines); y++ { if len(lines[y]) < ret.BottomRight.X { break } ret.BottomRight.Y = y for x := 0; x < len(lines[y]); x++ { ret.BottomRight.X = x ret.Area[h.Coordinate{X: x, Y: y}] = lines[y][x] == '#' } } ret.SaveToHistory() return &ret } func (l Layout) SaveToHistory() { l.History[l.String()] = l.Rating() } func (l Layout) Rating() float64 { var rating, pow float64 for y := 0; y <= l.BottomRight.Y; y++ { for x := 0; x <= l.BottomRight.X; x++ { if l.Area[h.Coordinate{X: x, Y: y}] { rating = rating + math.Pow(2, pow) } pow++ } } return rating } func (l Layout) Step() bool { a := make(map[h.Coordinate]bool) for k, v := range l.Area { a[k] = v } for y := 0; y <= l.BottomRight.Y; y++ { for x := 0; x <= l.BottomRight.X; x++ { c := h.Coordinate{X: x, Y: y} neighbors := 0 for _, v := range []h.Coordinate{c.North(), c.East(), c.South(), c.West()} { if n, ok := l.Area[v]; ok && n { neighbors++ } } if l.Area[c] { if neighbors != 1 { a[c] = false } } else { if neighbors == 1 || neighbors == 2 { a[c] = true } } } } for k, v := range a { l.Area[k] = v } // Finally check/save to history _, ok := l.History[l.String()] l.History[l.String()] = l.Rating() return ok } func (l Layout) String() string { var ret string for y := 0; y <= l.BottomRight.Y; y++ { for x := 0; x <= l.BottomRight.X; x++ { if l.Area[h.Coordinate{X: x, Y: y}] { ret = ret + "#" } else { ret = ret + "." } } ret = ret + "\n" } return ret }