package main import ( "fmt" "math" "os" "strings" "time" h "git.bullercodeworks.com/brian/adventofcode/helpers" ) var part = -1 var testRow = 2000000 var watch bool var watchRows = 1 func main() { inp := h.StdinToStringSlice() if len(os.Args) > 1 { for _, arg := range os.Args[1:] { if strings.HasPrefix(arg, "--part") || strings.HasPrefix(arg, "-p") { if strings.Contains(arg, "=") { pts := strings.Split(arg, "=") part = h.Atoi(pts[1]) } } else if strings.HasPrefix(arg, "--row") || strings.HasPrefix(arg, "-r") { if strings.Contains(arg, "=") { pts := strings.Split(arg, "=") testRow = h.Atoi(pts[1]) } } else if strings.HasPrefix(arg, "--watch") || strings.HasPrefix(arg, "-w") { watch = true if strings.Contains(arg, "=") { pts := strings.Split(arg, "=") if pts[1] == "full" { watchRows = -1 } else { watchRows = h.Atoi(pts[1]) } } } } } if part == 1 || part == -1 { part1(inp) } if part == 2 || part == -1 { part2(inp) } } func part1(inp []string) { min_x, max_x := math.MaxInt, math.MinInt var spots [][]int for i := range inp { s, b := strToCoords(inp[i]) xs, ys, xb, yb := s.X, s.Y, b.X, b.Y dist := s.Distance(b) l, r := xs-dist, xs+dist min_x = h.Min(min_x, l) max_x = h.Max(max_x, r) spots = append(spots, []int{xs, ys, xb, yb, dist}) } var nopeCount int for x := min_x; x <= max_x; x++ { for _, c := range spots { if x == c[2] && testRow == c[3] { break } if h.ManhattanDistance(x, testRow, c[0], c[1]) <= c[4] { nopeCount++ break } } } fmt.Println("# Part 1") fmt.Println(nopeCount) } type Sensor struct { c h.Coordinate // Sensor Position b h.Coordinate // Beacon Position d int // Distance } func (s Sensor) isInRange(c h.Coordinate) bool { return s.c.Distance(c) <= s.d } func (s Sensor) String() string { return s.c.String() } func part2(inp []string) { var sensors []Sensor for i := range inp { s := Sensor{} s.c, s.b = strToCoords(inp[i]) s.d = s.c.Distance(s.b) sensors = append(sensors, s) } max := testRow * 2 found := []h.Coordinate{} // Check around each sensor, the beacon must be it's distance + 1 for _, sensor := range sensors { d := sensor.d + 1 testEnds := []h.Coordinate{ {X: sensor.c.X, Y: sensor.c.Y - d}, {X: sensor.c.X + d, Y: sensor.c.Y}, {X: sensor.c.X, Y: sensor.c.Y + d}, {X: sensor.c.X - d, Y: sensor.c.Y}, } printMap(sensors, max, max, h.Coordinate{X: math.MinInt, Y: math.MinInt}) var tstX, tstY int for i := 0; i < 3; i++ { // Test all spots between testEnds[i] & testEnds[i+1] for tstX != testEnds[i+1].X && tstY != testEnds[i+1].Y { if testEnds[i].X < testEnds[i+1].X { tstX++ if testEnds[i].Y < testEnds[i+1].Y { tstY++ } else { tstY-- } } else { tstX-- if testEnds[i].Y < testEnds[i+1].Y { tstY++ } else { tstY-- } } } if tstX <= max && tstY <= max { fmt.Print(h.CLEAR_SCREEN) printMap(sensors, max, max, h.Coordinate{X: tstX, Y: tstY}) fmt.Println("Testing", tstX, ",", tstY) time.Sleep(time.Second / 10) if testSpot(tstX, tstY, sensors) { found = append(found, h.Coordinate{X: tstX, Y: tstY}) } } } } fmt.Println("# Part 2") fmt.Println(found) //fmt.Println((found.X * 4000000) + found.Y) } func testSpot(x, y int, sensors []Sensor) bool { var wasInRange bool for i := range sensors { if sensors[i].isInRange(h.Coordinate{X: x, Y: y}) { wasInRange = true break } } return !wasInRange } func printMap(sensors []Sensor, ceilX, ceilY int, tstPos h.Coordinate) { minX, maxX, minY, maxY := math.MaxInt, math.MinInt, math.MaxInt, math.MinInt for i := range sensors { minX = h.Min(sensors[i].b.X, minX) maxX = h.Max(sensors[i].b.X, maxX) minY = h.Min(sensors[i].b.Y, minY) maxY = h.Max(sensors[i].b.Y, maxY) } for y := minY; y <= maxY; y++ { for x := minX; x <= maxX; x++ { wrk := h.Coordinate{X: x, Y: y} var found bool for _, sensor := range sensors { if sensor.c.Equals(wrk) { fmt.Print("S") found = true break } else if sensor.b.Equals(wrk) { fmt.Print("B") found = true break } else if sensor.isInRange(wrk) { fmt.Print("#") found = true break } } if !found { if wrk.Equals(tstPos) { fmt.Print(h.FILL_CHAR) } else { fmt.Print(".") } } } fmt.Println() } } func strToCoords(s string) (h.Coordinate, h.Coordinate) { var sensor, beacon h.Coordinate r := strings.NewReader(s) fmt.Fscanf(r, "Sensor at x=%d, y=%d: closest beacon is at x=%d, y=%d", &sensor.X, &sensor.Y, &beacon.X, &beacon.Y) return sensor, beacon }