123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- package main
-
- import (
- "fmt"
- "github.com/csmith/aoc-2019/common"
- "github.com/csmith/aoc-2019/intcode"
- )
-
- type tile uint8
- type direction int
-
- const (
- unknown tile = iota
- wall tile = iota
- open tile = iota
- start tile = iota
- oxygen tile = iota
- filled tile = iota
-
- north direction = 1
- south direction = 2
- west direction = 3
- east direction = 4
- )
-
- var directions = [4]direction{north, south, west, east}
-
- type step struct {
- vm *intcode.VirtualMachine
- x int
- y int
- steps int
- }
-
- func (s step) next(direction direction) (int, int) {
- switch direction {
- case north:
- return s.x, s.y - 1
- case south:
- return s.x, s.y + 1
- case west:
- return s.x - 1, s.y
- case east:
- return s.x + 1, s.y
- }
- panic(fmt.Sprintf("unknown direction: %v", direction))
- }
-
- func explore(vm *intcode.VirtualMachine) (grid [100][100]tile, stepsToOxygen int, oxygenX int, oxygenY int) {
- queue := make(chan step, 100)
-
- queue <- step{
- vm: vm,
- x: 50,
- y: 50,
- }
- grid[50][50] = start
-
- for {
- select {
- case s := <-queue:
- for _, d := range directions {
- xp, yp := s.next(d)
-
- if grid[yp][xp] != unknown {
- continue
- }
-
- vmp := s.vm.Clone()
- go vmp.Run()
- vmp.Input <- int(d)
- state := <-vmp.Output
-
- if state == 0 {
- grid[yp][xp] = wall
- } else {
- if state == 2 {
- grid[yp][xp] = oxygen
- stepsToOxygen = s.steps + 1
- oxygenX = xp
- oxygenY = yp
- } else {
- grid[yp][xp] = open
- }
-
- queue <- step{
- vm: vmp,
- x: xp,
- y: yp,
- steps: s.steps + 1,
- }
- }
- }
- default:
- return
- }
- }
- }
-
- func disperse(grid [100][100]tile, x, y int) (maxSteps int) {
- queue := make(chan step, 100)
-
- queue <- step{
- x: x,
- y: y,
- }
-
- for {
- select {
- case s := <-queue:
- maxSteps = common.Max(maxSteps, s.steps)
- for _, d := range directions {
- xp, yp := s.next(d)
-
- if grid[yp][xp] == filled || grid[yp][xp] == wall {
- continue
- }
-
- grid[yp][xp] = filled
-
- queue <- step{
- x: xp,
- y: yp,
- steps: s.steps + 1,
- }
- }
- default:
- return
- }
- }
- }
-
- func main() {
- input := common.ReadCsvAsInts("15/input.txt")
- memory := make([]int, len(input))
- copy(memory, input)
- vm := intcode.NewVirtualMachine(memory)
- vm.Input = make(chan int, 1)
- vm.Output = make(chan int, 1)
- go vm.Run()
-
- grid, stepsToOxygen, oxyX, oxyY := explore(vm)
-
- println(stepsToOxygen)
- println(disperse(grid, oxyX, oxyY))
- }
|