This gets runtime down to about a quarter of what it was. I need to see if I can apply bisect to the X value, but I'm not sure I understand how/if that can work.
123 lines
2.0 KiB
Go
123 lines
2.0 KiB
Go
package days
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
u "parnic.com/aoc2019/utilities"
|
|
)
|
|
|
|
type Day19 struct {
|
|
program u.IntcodeProgram
|
|
}
|
|
|
|
func (d *Day19) Parse() {
|
|
d.program = u.LoadIntcodeProgram("19p")
|
|
}
|
|
|
|
func (d Day19) Num() int {
|
|
return 19
|
|
}
|
|
|
|
func (d *Day19) Part1() string {
|
|
grid := make([][]bool, 50)
|
|
for y := 0; y < len(grid); y++ {
|
|
grid[y] = make([]bool, 50)
|
|
}
|
|
|
|
count := int64(0)
|
|
|
|
for y := 0; y < 50; y++ {
|
|
for x := 0; x < 50; x++ {
|
|
d.program.Reset()
|
|
d.program.RunIn(func(inputStep int) int64 {
|
|
if inputStep == 1 {
|
|
return int64(x)
|
|
}
|
|
|
|
return int64(y)
|
|
}, func(val int64, state u.IntcodeProgramState) {
|
|
res := val == 1
|
|
grid[y][x] = res
|
|
if res {
|
|
count++
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// fmt.Println("50x50 tractor view:")
|
|
// for y := 0; y < len(grid); y++ {
|
|
// for x := 0; x < len(grid[y]); x++ {
|
|
// if grid[y][x] {
|
|
// fmt.Print("█")
|
|
// } else {
|
|
// fmt.Print(" ")
|
|
// }
|
|
// }
|
|
// fmt.Println()
|
|
// }
|
|
|
|
return fmt.Sprintf("Points affected in 50x50 area: %s%d%s", u.TextBold, count, u.TextReset)
|
|
}
|
|
|
|
func (d *Day19) Part2() string {
|
|
f := func(x, y int) bool {
|
|
ret := false
|
|
d.program.Reset()
|
|
d.program.RunIn(func(inputStep int) int64 {
|
|
if inputStep == 1 {
|
|
return int64(x)
|
|
}
|
|
return int64(y)
|
|
}, func(val int64, state u.IntcodeProgramState) {
|
|
ret = val == 1
|
|
})
|
|
|
|
return ret
|
|
}
|
|
|
|
// find lower bound
|
|
startY := 0
|
|
startX := 0
|
|
for y := 1; startY == 0; y++ {
|
|
for x := 0; x < 10*y; x++ {
|
|
if f(x, y) {
|
|
startY = y
|
|
startX = x
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
lastGoodX := 0
|
|
threshold := 1
|
|
y := u.Bisect(startY+100, 9999, threshold, func(y int) bool {
|
|
foundX := false
|
|
for x := startX; ; x++ {
|
|
if !f(x, y) {
|
|
if !foundX {
|
|
continue
|
|
} else {
|
|
return true
|
|
}
|
|
}
|
|
if !foundX {
|
|
foundX = true
|
|
}
|
|
|
|
if !f(x+99, y) {
|
|
return true
|
|
}
|
|
if !f(x, y+99) {
|
|
continue
|
|
}
|
|
|
|
lastGoodX = x
|
|
return false
|
|
}
|
|
})
|
|
|
|
result := (lastGoodX * 10000) + y
|
|
return fmt.Sprintf("Closest 100x100 square for the ship starts at %d,%d = %s%d%s", lastGoodX, y, u.TextBold, result, u.TextReset)
|
|
}
|