2021 - Day 20
This commit is contained in:
parent
1e481db7f1
commit
c1c4dcd7cf
9
2021/20/go.mod
Normal file
9
2021/20/go.mod
Normal file
|
@ -0,0 +1,9 @@
|
|||
module AoC/2021/20
|
||||
|
||||
require AoC/2021/common v0.0.0
|
||||
|
||||
require github.com/joho/godotenv v1.4.0 // indirect
|
||||
|
||||
replace AoC/2021/common v0.0.0 => ../common
|
||||
|
||||
go 1.17
|
2
2021/20/go.sum
Normal file
2
2021/20/go.sum
Normal file
|
@ -0,0 +1,2 @@
|
|||
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
|
||||
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
160
2021/20/main.go
Normal file
160
2021/20/main.go
Normal file
|
@ -0,0 +1,160 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
aoc "AoC/2021/common"
|
||||
"bufio"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Vec struct {
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
func (a Vec) Add(b Vec) Vec {
|
||||
return Vec{a.x+b.x, a.y+b.y}
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
data map[Vec]bool
|
||||
min Vec
|
||||
max Vec
|
||||
}
|
||||
|
||||
func NewImage() Image {
|
||||
var image Image
|
||||
image.data = make(map[Vec]bool)
|
||||
|
||||
return image
|
||||
}
|
||||
|
||||
func processInput(input *bufio.Scanner) (Image, string) {
|
||||
image := NewImage()
|
||||
|
||||
input.Scan()
|
||||
algorithm := input.Text()
|
||||
|
||||
input.Scan()
|
||||
for y := 0; input.Scan(); y++ {
|
||||
if y > image.max.y {
|
||||
image.max.y = y
|
||||
}
|
||||
line := input.Text()
|
||||
for x, c := range line {
|
||||
if x > image.max.x {
|
||||
image.max.x = x
|
||||
}
|
||||
|
||||
// Only store non-zero values
|
||||
if c == '#' {
|
||||
image.data[Vec{x,y}] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return image, algorithm
|
||||
}
|
||||
|
||||
func (image *Image) Print() {
|
||||
for y := image.min.y; y <= image.max.y; y++ {
|
||||
for x := image.min.x; x <= image.max.x; x++ {
|
||||
if image.Get(x, y, false) {
|
||||
fmt.Print("#")
|
||||
} else {
|
||||
fmt.Print(".")
|
||||
}
|
||||
}
|
||||
fmt.Print("\n")
|
||||
}
|
||||
fmt.Print("\n")
|
||||
}
|
||||
|
||||
func (image *Image) Get(x int, y int, outside bool) bool {
|
||||
if x < image.min.x || x > image.max.x || y < image.min.y || y > image.max.y {
|
||||
return outside
|
||||
}
|
||||
return image.data[Vec{x, y}]
|
||||
}
|
||||
|
||||
func (image *Image) Kernel(x int, y int, algorithm string, outside bool) bool {
|
||||
index := 0
|
||||
for dy := -1; dy <= 1; dy++ {
|
||||
for dx := -1; dx <= 1; dx++ {
|
||||
index <<= 1
|
||||
if image.Get(x+dx, y+dy, outside) {
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if algorithm[index] == '#' {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (image *Image) Enhance(algorithm string, outside bool) Image {
|
||||
newImage := NewImage()
|
||||
newImage.min = image.min.Add(Vec{-1, -1})
|
||||
newImage.max = image.max.Add(Vec{1, 1})
|
||||
|
||||
for y := newImage.min.y; y <= newImage.max.y; y++ {
|
||||
for x := newImage.min.x; x <= newImage.max.x; x++ {
|
||||
if image.Kernel(x, y, algorithm, outside) {
|
||||
newImage.data[Vec{x,y}] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newImage
|
||||
}
|
||||
|
||||
func (image *Image) Count() int {
|
||||
return len(image.data)
|
||||
}
|
||||
|
||||
func main() {
|
||||
challenge := aoc.New(2021, 20)
|
||||
|
||||
challenge.Test(`..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..###..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.###.######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#..#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#......#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#.....####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#.......##..####..#...#.#.#...##..#.#..###..#####........#..####......#..#
|
||||
|
||||
#..#.
|
||||
#....
|
||||
##..#
|
||||
..#..
|
||||
..###`, []int{35, 3351})
|
||||
|
||||
challenge.Solution(1, func (input *bufio.Scanner) int {
|
||||
image, algorithm := processInput(input)
|
||||
|
||||
round1 := image.Enhance(algorithm, false)
|
||||
|
||||
alternate := false
|
||||
if algorithm[0] == '#' {
|
||||
alternate = true
|
||||
}
|
||||
|
||||
round2 := round1.Enhance(algorithm, alternate)
|
||||
|
||||
return round2.Count()
|
||||
})
|
||||
|
||||
// @NOTE This solution does not actually properly handle the algorithm[0] == '#' edge case
|
||||
// Here we assume that the last char in the algorithm is '.' and therefore alternate betwee # and . outside
|
||||
// However if the last char is # we keep # outside after the first round
|
||||
// For my input this was not the case, but it is an oversight
|
||||
challenge.Solution(2, func (input *bufio.Scanner) int {
|
||||
image, algorithm := processInput(input)
|
||||
|
||||
alternate := false
|
||||
for round := 0; round < 50; round++ {
|
||||
image = image.Enhance(algorithm, alternate)
|
||||
if algorithm[0] == '#' {
|
||||
alternate = !alternate
|
||||
}
|
||||
}
|
||||
|
||||
return image.Count()
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user