diff --git a/20/main.go b/20/main.go new file mode 100644 index 0000000..183f83a --- /dev/null +++ b/20/main.go @@ -0,0 +1,165 @@ +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++ + } + + img.Print() + fmt.Println(img.CountBrightPixels()) + fmt.Println("") + + for i := 0; i < 2; i++ { + img = Enhance(img, enhancementString) + img.Print() + fmt.Println(img.CountBrightPixels()) + fmt.Println("") + } +} + +func partTwo() { + scanner := makeScanner(false) + + for scanner.Scan() { + // line := scanner.Text() + } +} diff --git a/20/main_test.go b/20/main_test.go new file mode 100644 index 0000000..69792f8 --- /dev/null +++ b/20/main_test.go @@ -0,0 +1,66 @@ +package main + +import ( + "strings" + "testing" +) + +func TestGetNewRune(t *testing.T) { + img := image{ + grid: map[coord]rune{ + {0, 0}: '.', {1, 0}: '.', {2, 0}: '.', + {0, 1}: '.', {1, 1}: '.', {2, 1}: '.', + {0, 2}: '.', {1, 2}: '.', {2, 2}: '.', + }, + } + if img.GetNewRune(coord{1, 1}, ".") != '.' { + t.Fail() + } + + img = image{ + grid: map[coord]rune{ + {0, 0}: '.', {1, 0}: '.', {2, 0}: '.', + {0, 1}: '.', {1, 1}: '.', {2, 1}: '.', + {0, 2}: '.', {1, 2}: '.', {2, 2}: '#', + }, + } + if img.GetNewRune(coord{1, 1}, ".#") != '#' { + t.Fail() + } + + img = image{ + grid: map[coord]rune{ + {0, 0}: '.', {1, 0}: '.', {2, 0}: '.', + {0, 1}: '.', {1, 1}: '.', {2, 1}: '.', + {0, 2}: '.', {1, 2}: '#', {2, 2}: '.', + }, + } + if img.GetNewRune(coord{1, 1}, "..#.") != '#' { + t.Fail() + } + + img = image{ + grid: map[coord]rune{ + {0, 0}: '.', {1, 0}: '.', {2, 0}: '.', + {0, 1}: '.', {1, 1}: '.', {2, 1}: '.', + {0, 2}: '.', {1, 2}: '#', {2, 2}: '#', + }, + } + if img.GetNewRune(coord{1, 1}, "...#") != '#' { + t.Fail() + } + + img = image{ + background: '#', + grid: map[coord]rune{ + {0, 0}: '.', {1, 0}: '.', {2, 0}: '.', + {0, 1}: '.', {1, 1}: '.', {2, 1}: '.', + {0, 2}: '.', {1, 2}: '#', {2, 2}: '#', + }, + } + m := strings.Repeat(".", 484) + m += "#" + if img.GetNewRune(coord{0, 0}, m) != '#' { // 111100100, or 484 + t.Fail() + } +}