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 bot, _ := 1025, 1037 for square != shipSize { bot++ fmt.Print("Calculating ", bot, "... ") square, x = maxSquare(prog, bot, bot/2) fmt.Println(square) } fmt.Println(x, bot) } func part2Almost(prog []int) { shipSize := 100 // Guesses x, y := 0, 1000 var square int bot, top := 1026, 1037 square, x = maxSquare(prog, y, 0) lastCheckRow := y for { if square > shipSize { y = y - (y-bot)/2 } else if square < shipSize { y = y + (top-y)/2 } if lastCheckRow == y { break } lastCheckRow = y fmt.Print("Calculating at ", y, "... ") square, x = maxSquare(prog, y, (y / 2)) if square > 100 && y < top { top = y } else if square < 100 && y > bot { bot = y } fmt.Println("Square:", square) } fmt.Println("Final Square:", square) fmt.Println(x, y) } 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) }