113 lines
2.2 KiB
Go
113 lines
2.2 KiB
Go
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
|
|
}
|