package main import ( "bufio" "fmt" "os" "strings" "time" ) func main() { start := time.Now() partOne() duration := time.Since(start) partTwo() duration2 := time.Since(start) fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration) } func makeScanner(test bool) *bufio.Scanner { var f *os.File if test { f, _ = os.Open("inputs/testinput") } else { f, _ = os.Open("inputs/input") } reader := bufio.NewReader(f) return bufio.NewScanner(reader) } type coord struct { x int y int } // grid SHOULD be like this: // x -> // y // | // V type image struct { background rune // what all uninitialized cells are set to; defaults to '.' grid map[coord]rune topleft coord size int } func GetNeighbors(c coord) []coord { return []coord{ {x: c.x - 1, y: c.y - 1}, {x: c.x, y: c.y - 1}, {x: c.x + 1, y: c.y - 1}, {x: c.x - 1, y: c.y}, {x: c.x, y: c.y}, {x: c.x + 1, y: c.y}, {x: c.x - 1, y: c.y + 1}, {x: c.x, y: c.y + 1}, {x: c.x + 1, y: c.y + 1}, } } func (img *image) GetNewRune(coord coord, enhancementMap string) rune { index := 0 coords := GetNeighbors(coord) for i := 0; i < len(coords); i++ { value := img.grid[coords[i]] if value == 0 { value = img.background } if value == '#' { index += (1 << (8 - i)) } } return rune(enhancementMap[index]) } func (img *image) CountBrightPixels() int { count := 0 for _, v := range img.grid { if v == '#' { count++ } } return count } func (img *image) Print() { fmt.Println(strings.Repeat(string(img.background), img.size+2)) for y := img.topleft.y; y < img.size+img.topleft.y; y++ { fmt.Print(string(img.background)) for x := img.topleft.x; x < img.size+img.topleft.x; x++ { fmt.Printf("%s", string(img.grid[coord{x, y}])) } fmt.Printf("%s\n", string(img.background)) } fmt.Println(strings.Repeat(string(img.background), img.size+2)) } func Enhance(img *image, m string) *image { next := &image{ topleft: coord{ x: img.topleft.x - 1, y: img.topleft.y - 1, }, size: img.size + 2, grid: map[coord]rune{}, } if img.background == '.' { // permute new "background" value next.background = rune(m[0]) } else if img.background == '#' { next.background = rune(m[511]) } for y := img.topleft.y - 1; y < img.size+1; y++ { for x := img.topleft.x - 1; x < img.size+1; x++ { next.grid[coord{x, y}] = img.GetNewRune(coord{x, y}, m) } } return next } func partOne() { scanner := makeScanner(false) scanner.Scan() enhancementString := scanner.Text() scanner.Scan() // eat empty line img := &image{ background: '.', grid: map[coord]rune{}, topleft: coord{0, 0}, } y := 0 for scanner.Scan() { line := scanner.Text() img.size = len(line) for x, c := range line { img.grid[coord{x, y}] = c } y++ } for i := 0; i < 2; i++ { img = Enhance(img, enhancementString) } fmt.Println(img.CountBrightPixels()) } func partTwo() { scanner := makeScanner(false) scanner.Scan() enhancementString := scanner.Text() scanner.Scan() // eat empty line img := &image{ background: '.', grid: map[coord]rune{}, topleft: coord{0, 0}, } y := 0 for scanner.Scan() { line := scanner.Text() img.size = len(line) for x, c := range line { img.grid[coord{x, y}] = c } y++ } for i := 0; i < 50; i++ { img = Enhance(img, enhancementString) } fmt.Println(img.CountBrightPixels()) }