2019-12-19 15:28:46 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
intcode "git.bullercodeworks.com/brian/adventofcode/2019/intcode-processor"
|
|
|
|
helpers "git.bullercodeworks.com/brian/adventofcode/helpers"
|
|
|
|
)
|
|
|
|
|
|
|
|
var beam map[string]int
|
|
|
|
var maxY int
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
pt := helpers.GetArgNumber(1)
|
|
|
|
prog := intcode.ReadIntCodeFile("input")
|
|
|
|
beam = make(map[string]int)
|
|
|
|
if pt == "1" {
|
|
|
|
part1(prog)
|
|
|
|
} else {
|
|
|
|
part2(prog)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func part1(prog []int) {
|
|
|
|
var count int
|
|
|
|
var lastRowStart int
|
|
|
|
for y := 0; y < 50; y++ {
|
|
|
|
var foundFirst bool
|
|
|
|
fmt.Print(strings.Repeat(" ", lastRowStart))
|
|
|
|
for x := lastRowStart; x < 50; x++ {
|
|
|
|
out := runCodeAt(prog, x, y)
|
|
|
|
fmt.Print(out)
|
|
|
|
beam[c(x, y)] = out
|
|
|
|
if out == 1 {
|
|
|
|
if !foundFirst {
|
|
|
|
lastRowStart = x
|
|
|
|
}
|
|
|
|
foundFirst = true
|
|
|
|
count++
|
|
|
|
} else if foundFirst {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fmt.Println()
|
|
|
|
maxY = y
|
|
|
|
}
|
|
|
|
fmt.Println("Total:", count)
|
|
|
|
}
|
|
|
|
|
|
|
|
func part2(prog []int) {
|
|
|
|
shipSize := 100
|
|
|
|
// Guesses
|
|
|
|
//x, y := 0, 1000
|
|
|
|
var x, square int
|
2019-12-23 13:05:56 +00:00
|
|
|
bot, _ := 1034, 1038
|
2019-12-19 15:28:46 +00:00
|
|
|
for square != shipSize {
|
|
|
|
bot++
|
|
|
|
fmt.Print("Calculating ", bot, "... ")
|
|
|
|
square, x = maxSquare(prog, bot, bot/2)
|
|
|
|
fmt.Println(square)
|
|
|
|
}
|
2019-12-23 13:05:56 +00:00
|
|
|
fmt.Println(x, (bot+1)-100)
|
2019-12-19 15:28:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func part2Slow(prog []int) {
|
|
|
|
shipSize := 100
|
|
|
|
var x, y int
|
|
|
|
retX, retY := -1, -1
|
|
|
|
var lastRowStart int
|
|
|
|
for y = maxY; true; y++ {
|
|
|
|
var foundFirst bool
|
|
|
|
fmt.Print(strings.Repeat(" ", lastRowStart))
|
|
|
|
for x = lastRowStart; x < y; x++ {
|
|
|
|
out := runCodeAt(prog, x, y)
|
|
|
|
fmt.Print(out)
|
|
|
|
beam[c(x, y)] = out
|
|
|
|
if out == 1 {
|
|
|
|
if !foundFirst {
|
|
|
|
lastRowStart = x
|
|
|
|
}
|
|
|
|
foundFirst = true
|
|
|
|
} else if foundFirst {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
square, _ := maxSquare(prog, y, lastRowStart)
|
|
|
|
fmt.Println(":", square)
|
|
|
|
// Every row, check what the maximum square is
|
|
|
|
if square >= shipSize {
|
|
|
|
retY, retX = y, lastRowStart
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fmt.Println(retX, ",", retY)
|
|
|
|
}
|
|
|
|
|
|
|
|
// maxSquare returns the square size and the bottom-left x position it starts at
|
|
|
|
func maxSquare(prog []int, row, firstX int) (int, int) {
|
|
|
|
for ; firstX < row; firstX++ {
|
|
|
|
// Find the first X
|
|
|
|
if runCodeAt(prog, firstX, row) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
var square int
|
|
|
|
for d := 0; true; d++ {
|
|
|
|
if runCodeAt(prog, firstX+d, row-d) == 0 {
|
|
|
|
return square, firstX
|
|
|
|
}
|
|
|
|
square++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0, firstX
|
|
|
|
}
|
|
|
|
|
|
|
|
func runCodeAt(prog []int, x, y int) int {
|
|
|
|
// If we've already cached this pos, just return it
|
|
|
|
if v, ok := beam[c(x, y)]; ok {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
var res int
|
|
|
|
p := intcode.NewProgram(prog)
|
|
|
|
go func() {
|
|
|
|
sendInputs(p, []int{x, y})
|
|
|
|
res = getOutput(p)
|
|
|
|
}()
|
|
|
|
p.Run()
|
|
|
|
|
|
|
|
beam[c(x, y)] = res
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
|
|
|
func sendInputs(p *intcode.Program, inp []int) {
|
|
|
|
for k := range inp {
|
|
|
|
for !p.NeedsInput() {
|
|
|
|
time.Sleep(1)
|
|
|
|
}
|
|
|
|
p.Input(inp[k])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func getOutput(p *intcode.Program) int {
|
|
|
|
for !p.NeedsOutput() {
|
|
|
|
time.Sleep(1)
|
|
|
|
}
|
|
|
|
return p.Output()
|
|
|
|
}
|
|
|
|
|
|
|
|
func c(x, y int) string {
|
|
|
|
return fmt.Sprintf("[%d, %d]", x, y)
|
|
|
|
}
|