2021 Day 20
This commit is contained in:
parent
0af5fe823c
commit
62aef27970
1 changed files with 154 additions and 0 deletions
154
2021/day20/main.go
Normal file
154
2021/day20/main.go
Normal file
|
|
@ -0,0 +1,154 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/fatih/color"
|
||||||
|
"github.com/jdkaplan/advent-of-code/aoc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
text := aoc.Input().ReadFile("day20.txt")
|
||||||
|
alg, img := parseInput(text)
|
||||||
|
fmt.Println(run(alg, img, 2))
|
||||||
|
fmt.Println(run(alg, img, 50))
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseInput(text string) (Alg, Image) {
|
||||||
|
alg, img := aoc.Cut(text, "\n\n")
|
||||||
|
lines := strings.Split(img, "\n")
|
||||||
|
return NewAlg(alg), NewImage(lines)
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(alg Alg, img Image, n int) int {
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
img = tick(alg, img)
|
||||||
|
}
|
||||||
|
return len(img.light)
|
||||||
|
}
|
||||||
|
|
||||||
|
func tick(alg Alg, img Image) Image {
|
||||||
|
light := make(map[RC]struct{})
|
||||||
|
for r := img.rmin - 1; r <= img.rmax+1; r++ {
|
||||||
|
for c := img.cmin - 1; c <= img.cmax+1; c++ {
|
||||||
|
rc := RC{r, c}
|
||||||
|
x := img.Next(rc)
|
||||||
|
if alg.Apply(x) {
|
||||||
|
light[rc] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Image{
|
||||||
|
light,
|
||||||
|
!img.border,
|
||||||
|
img.rmin - 1, img.rmax + 1,
|
||||||
|
img.cmin - 1, img.cmax + 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type RC struct{ r, c int }
|
||||||
|
|
||||||
|
type Image struct {
|
||||||
|
light map[RC]struct{}
|
||||||
|
border bool
|
||||||
|
rmin, rmax int
|
||||||
|
cmin, cmax int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewImage(lines []string) (img Image) {
|
||||||
|
img.rmin, img.rmax = 0, len(lines)
|
||||||
|
img.cmin, img.cmax = 0, len(lines[0])
|
||||||
|
img.light = make(map[RC]struct{})
|
||||||
|
for r, line := range lines {
|
||||||
|
for c, char := range line {
|
||||||
|
if lightChar(char) {
|
||||||
|
img.light[RC{r, c}] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Image) String() string {
|
||||||
|
var sb strings.Builder
|
||||||
|
pad := 4
|
||||||
|
dim, bright := color.New(color.FgWhite), color.New(color.FgHiWhite)
|
||||||
|
for r := i.rmin - pad; r <= i.rmax+pad; r++ {
|
||||||
|
for c := i.cmin - pad; c <= i.cmax+pad; c++ {
|
||||||
|
rc := RC{r, c}
|
||||||
|
f := dim
|
||||||
|
if i.Inbounds(rc) {
|
||||||
|
f = bright
|
||||||
|
}
|
||||||
|
if i.IsLight(rc) {
|
||||||
|
f.Fprint(&sb, "#")
|
||||||
|
} else {
|
||||||
|
f.Fprint(&sb, ".")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.WriteString("\n")
|
||||||
|
}
|
||||||
|
return sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Image) IsLight(rc RC) bool {
|
||||||
|
if i.Inbounds(rc) {
|
||||||
|
_, ok := i.light[rc]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
return i.border
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Image) Inbounds(rc RC) bool {
|
||||||
|
r, c := rc.r, rc.c
|
||||||
|
return i.rmin <= r && r <= i.rmax && i.cmin <= c && c <= i.cmax
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Image) Next(rc RC) uint {
|
||||||
|
var x uint
|
||||||
|
for j, n := range rc.Neighbors() {
|
||||||
|
if i.IsLight(n) {
|
||||||
|
x |= 1 << (8 - j)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc RC) Neighbors() []RC {
|
||||||
|
r, c := rc.r, rc.c
|
||||||
|
return []RC{
|
||||||
|
{r - 1, c - 1}, {r - 1, c}, {r - 1, c + 1},
|
||||||
|
{r, c - 1}, {r, c}, {r, c + 1},
|
||||||
|
{r + 1, c - 1}, {r + 1, c}, {r + 1, c + 1},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Alg map[uint]struct{}
|
||||||
|
|
||||||
|
func NewAlg(line string) Alg {
|
||||||
|
alg := make(Alg)
|
||||||
|
for i := uint(0); i < uint(len(line)); i++ {
|
||||||
|
if lightChar(rune(line[i])) {
|
||||||
|
alg[i] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return alg
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Alg) Apply(n uint) (light bool) {
|
||||||
|
_, ok := a[n]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func lightChar(r rune) bool {
|
||||||
|
switch r {
|
||||||
|
case '#':
|
||||||
|
return true
|
||||||
|
case '.':
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
panic(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue