125 lines
2.2 KiB
Go
125 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
|
)
|
|
|
|
const (
|
|
White = iota
|
|
Black
|
|
)
|
|
|
|
var tiles map[h.Coordinate]bool
|
|
|
|
func init() {
|
|
tiles = make(map[h.Coordinate]bool)
|
|
}
|
|
|
|
func main() {
|
|
fmt.Println("# Day 24")
|
|
inp := h.StdinToStringSlice()
|
|
|
|
solve(inp, h.Atoi(h.OptArgNumber(1, "2")))
|
|
}
|
|
|
|
func solve(inp []string, part int) {
|
|
buildTiles(inp)
|
|
if part == 1 {
|
|
fmt.Println("## Part 1\nAnswer:", len(tiles))
|
|
} else {
|
|
for day := 1; day <= 100; day++ {
|
|
next := make(map[h.Coordinate]bool)
|
|
lx, ly, hx, hy := getBordering()
|
|
for y := ly; y <= hy; y++ {
|
|
for x := lx; x <= hx; x++ {
|
|
tst := h.Coordinate{X: x, Y: y}
|
|
_, ok := tiles[tst]
|
|
bl := CountTiles(GetAllNeighborCoords(tst))
|
|
if (ok && !(bl == 0 || bl > 2)) || (!ok && bl == 2) {
|
|
next[tst] = true
|
|
}
|
|
}
|
|
}
|
|
tiles = next
|
|
fmt.Printf("Day %d: %d\n", day, len(next))
|
|
}
|
|
}
|
|
}
|
|
|
|
func getBordering() (int, int, int, int) {
|
|
lx, ly, hx, hy := h.MAX_INT, h.MAX_INT, h.MIN_INT, h.MIN_INT
|
|
for k := range tiles {
|
|
lx = h.Min(lx, k.X)
|
|
ly = h.Min(ly, k.Y)
|
|
hx = h.Max(hx, k.X)
|
|
hy = h.Max(hy, k.Y)
|
|
}
|
|
return lx - 1, ly - 1, hx + 1, hy + 1
|
|
}
|
|
|
|
/*
|
|
o o
|
|
o o o
|
|
o o
|
|
*/
|
|
func buildTiles(inp []string) {
|
|
for k := range inp {
|
|
curr := h.Coordinate{}
|
|
var last rune
|
|
for _, r := range inp[k] {
|
|
if r == 'n' || r == 's' {
|
|
last = r
|
|
continue
|
|
}
|
|
curr = GetNeighborCoord(curr, last+r)
|
|
last = 0
|
|
}
|
|
if v := tiles[curr]; v {
|
|
delete(tiles, curr)
|
|
} else {
|
|
tiles[curr] = true
|
|
}
|
|
}
|
|
}
|
|
|
|
func CountTiles(c []h.Coordinate) int {
|
|
var ret int
|
|
for _, v := range c {
|
|
if _, ok := tiles[v]; ok {
|
|
ret++
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func GetAllNeighborCoords(c h.Coordinate) []h.Coordinate {
|
|
var ret []h.Coordinate
|
|
for _, v := range []rune{
|
|
'e', 'n' + 'e', 's' + 'e', 'w', 'n' + 'w', 's' + 'w',
|
|
} {
|
|
ret = append(ret, GetNeighborCoord(c, v))
|
|
}
|
|
return ret
|
|
}
|
|
|
|
// Translate hex neighbors into a 2d plane
|
|
func GetNeighborCoord(c h.Coordinate, dir rune) h.Coordinate {
|
|
switch dir {
|
|
case 'e':
|
|
return c.East()
|
|
case 'n' + 'e':
|
|
return c.North()
|
|
case 's' + 'e':
|
|
return c.South().East()
|
|
case 'w':
|
|
return c.West()
|
|
case 'n' + 'w':
|
|
return c.North().West()
|
|
case 's' + 'w':
|
|
return c.South()
|
|
}
|
|
return c
|
|
}
|