package main
import (
"bufio"
"log"
"os"
"strconv"
"strings"
)
type point struct {
row, col int
}
type pixels map[point]bool
type image struct {
IEA string
m pixels
size int
flippy bool
}
var directions = [][2]int{
{-1, -1},
{-1, 0},
{-1, 1},
{0, -1},
{0, 0},
{0, 1},
{1, -1},
{1, 0},
{1, 1},
}
func main() {
if err := myMain(); err != nil {
log.Println(err)
}
}
func myMain() error {
in, err := parseInput("input.txt")
if err != nil {
return err
}
log.Println(solveFirst(in, 2))
log.Println(solveFirst(in, 50))
return nil
}
func solveFirst(in image, maxRounds int) int {
for round := 1; round <= maxRounds; round++ {
next := pixels{}
for row := -round; row < in.size+round; row++ {
for col := -round; col < in.size+round; col++ {
p := point{row, col}
next.getValue(in, p, round)
}
}
in.m = next
if in.IEA[0] == '#' && in.IEA[len(in.IEA)-1] == '.' {
in.flippy = !in.flippy
}
}
return len(in.m)
}
func (next pixels) getValue(in image, p point, round int) {
binary := strings.Builder{}
for _, d := range directions {
p := point{p.row + d[0], p.col + d[1]}
if in.flippy &&
(p.row < -round+1 || p.row >= in.size+round-1 ||
p.col < -round+1 || p.col >= in.size+round-1) {
binary.WriteByte('1')
continue
}
if in.m[p] {
binary.WriteByte('1')
} else {
binary.WriteByte('0')
}
}
bin, err := strconv.ParseUint(binary.String(), 2, 9)
if err != nil {
log.Panicln(err)
}
if in.IEA[bin] == '#' {
next[p] = true
}
}
func parseInput(fileName string) (image, error) {
ret := image{}
ret.m = map[point]bool{}
fd, err := os.Open(fileName)
if err != nil {
return ret, err
}
defer fd.Close()
buf := bufio.NewScanner(fd)
for line := 0; buf.Scan(); line++ {
if line == 0 {
ret.IEA = buf.Text()
continue
}
for i, ch := range buf.Text() {
if ch == '#' {
ret.m[point{line - 2, i}] = true
}
}
ret.size = line - 1
}
return ret, nil
}