123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- package main
-
- import (
- "fmt"
- "github.com/csmith/aoc-2019/common"
- "github.com/csmith/aoc-2019/intcode"
- "strconv"
- )
-
- const (
- up = '^'
- down = 'v'
- left = '<'
- right = '>'
- borked = 'X'
- )
-
- func rotate(from, to rune) rune {
- if from == up && to == left || from == left && to == down || from == down && to == right || from == right && to == up {
- return 'L'
- } else {
- return 'R'
- }
- }
-
- func next(picture [][]rune, x, y int, direction rune) (nextDirection, turn rune) {
- if x > 0 && direction != right && picture[y][x-1] == '#' {
- nextDirection = left
- } else if x < len(picture[0])-1 && direction != left && picture[y][x+1] == '#' {
- nextDirection = right
- } else if y > 0 && direction != down && picture[y-1][x] == '#' {
- nextDirection = up
- } else if y < len(picture)-1 && direction != up && picture[y+1][x] == '#' {
- nextDirection = down
- } else {
- return borked, borked
- }
-
- return nextDirection, rotate(direction, nextDirection)
- }
-
- func follow(picture [][]rune, x, y int, direction rune) (int, int, int) {
- deltaX, deltaY := 0, 0
- switch direction {
- case up:
- deltaY = -1
- case down:
- deltaY = 1
- case left:
- deltaX = -1
- case right:
- deltaX = +1
- case borked:
- return x, y, borked
- }
-
- length := 0
- for x+deltaX >= 0 && x+deltaX <= len(picture[0])-1 && y+deltaY >= 0 && y+deltaY <= len(picture)-1 && picture[y+deltaY][x+deltaX] == '#' {
- x += deltaX
- y += deltaY
- length++
- }
-
- return x, y, length
- }
-
- func readPicture(memory []int) [][]rune {
- vm := intcode.NewVirtualMachine(memory)
- vm.Input = make(chan int, 1)
- vm.Output = make(chan int, 1)
- go vm.Run()
-
- var picture [][]rune
- var currentRow []rune
- for {
- char, more := <-vm.Output
- if !more {
- break
- }
-
- if char == '\n' && len(currentRow) > 0 {
- picture = append(picture, currentRow)
- currentRow = make([]rune, 0)
- } else {
- currentRow = append(currentRow, rune(char))
- }
- }
- return picture
- }
-
- func analysePicture(picture [][]rune) (sum int, robot rune, robotX, robotY int) {
- robot = borked
- for y, line := range picture {
- for x, r := range line {
- if r == '#' &&
- x > 0 && line[x-1] == '#' &&
- x < len(line)-1 && line[x+1] == '#' &&
- y > 0 && picture[y-1][x] == '#' &&
- y < len(picture)-1 && picture[y+1][x] == '#' {
- sum += x * y
- }
-
- if r == up || r == down || r == left || r == right {
- robotX = x
- robotY = y
- robot = r
- }
- }
- }
- return
- }
-
- func buildRoute(picture [][]rune, robot rune, robotX, robotY int) []string {
- var (
- length int
- turn rune
- res []string
- )
- for {
- robot, turn = next(picture, robotX, robotY, robot)
- robotX, robotY, length = follow(picture, robotX, robotY, robot)
-
- if robot == borked {
- break
- }
-
- res = append(res, string(turn))
- res = append(res, strconv.Itoa(length))
- }
- return res
- }
-
- func calculateDust(input []int, m, a, b, c string) int {
- vm := intcode.NewVirtualMachine(input)
- vm.Input = make(chan int, 1)
- vm.Output = make(chan int, 1)
- vm.Memory[0] = 2
- go vm.Run()
-
- go func() {
- for _, line := range []string{m, a, b, c, "n"} {
- for _, r := range line {
- vm.Input <- int(r)
- }
- vm.Input <- '\n'
- }
- }()
-
- return common.Last(vm.Output)
- }
-
- func main() {
- input := common.ReadCsvAsInts("17/input.txt")
- memory := make([]int, len(input))
- copy(memory, input)
-
- picture := readPicture(input)
- sum, robot, robotX, robotY := analysePicture(picture)
- route := buildRoute(picture, robot, robotX, robotY)
- m, a, b, c := compress(route)
- dust := calculateDust(memory, m, a, b, c)
-
- fmt.Println(sum)
- fmt.Println(dust)
- }
|