From f00d2805fd705395bbde2d1a7a2501c36a4fe7b8 Mon Sep 17 00:00:00 2001 From: David Ashby Date: Mon, 26 Dec 2022 17:29:38 -0700 Subject: [PATCH] day 15 --- 15/main.go | 161 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 15/main.go diff --git a/15/main.go b/15/main.go new file mode 100644 index 0000000..c6c15f3 --- /dev/null +++ b/15/main.go @@ -0,0 +1,161 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" + "time" +) + +func mustAtoi(line string) int { + i, _ := strconv.Atoi(line) + return i +} + +func main() { + start := time.Now() + partOne() + duration := time.Since(start) + partTwo() + duration2 := time.Since(start) + fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration) +} + +func makeScanner(test bool) *bufio.Scanner { + var f *os.File + if test { + f, _ = os.Open("inputs/testinput") + } else { + f, _ = os.Open("inputs/input") + } + reader := bufio.NewReader(f) + return bufio.NewScanner(reader) +} + +type coord struct { + x int + y int +} + +func abs(i, j int) int { + if i < j { + return j - i + } + return i - j +} + +func getCoords(x, y string, _ bool) coord { + return coord{x: mustAtoi(x), y: mustAtoi(y)} +} + +func distance(sensor, beacon coord) int { + return abs(sensor.x, beacon.x) + abs(sensor.y, beacon.y) +} + +func partOne() { + test := false + scanner := makeScanner(test) + row := 2000000 + if test { + row = 10 + } + cave := map[coord]int{} // 0 for unknown space, 1 for sensor, 2 for beacon, 3 for known empty + + for scanner.Scan() { + line := scanner.Text() + s, b, _ := strings.Cut(line, ": ") + sensor := getCoords(strings.Cut(strings.Trim(s, "Sensor at x="), ", y=")) + beacon := getCoords(strings.Cut(strings.Trim(b, "closest beacon is at x="), ", y=")) + dist := distance(sensor, beacon) + cave[sensor] = 1 + cave[beacon] = 2 + rel := distance(sensor, coord{x: sensor.x, y: row}) + if rel <= dist { + c := dist - rel + for i := sensor.x - c; i <= sensor.x+c; i++ { + if _, ok := cave[coord{x: i, y: row}]; !ok { + cave[coord{x: i, y: row}] = 3 + } + } + } + } + sum := 0 + for _, i := range cave { + if i == 3 { + sum++ + } + } + fmt.Println(sum) +} + +func sensorHalo(sensor coord, distance int) []coord { + halo := []coord{} + corners := []coord{ + {x: sensor.x, y: sensor.y + distance + 1}, + {x: sensor.x + distance + 1, y: sensor.y}, + {x: sensor.x, y: sensor.y - distance - 1}, + {x: sensor.x - distance - 1, y: sensor.y}, + } + y := corners[0].y + for i := corners[0].x; i < corners[1].x; i++ { + halo = append(halo, coord{i, y}) + y-- + } + for i := corners[1].x; i > corners[2].x; i-- { + halo = append(halo, coord{i, y}) + y-- + } + for i := corners[2].x; i > corners[3].x; i-- { + halo = append(halo, coord{i, y}) + y++ + } + for i := corners[3].x; i > corners[0].x; i++ { + halo = append(halo, coord{i, y}) + y++ + } + halo = append(halo, corners[3]) + return halo +} + +func partTwo() { + test := false + scanner := makeScanner(test) + max := 4000000 + if test { + max = 20 + } + cave := map[coord]int{} // sensor: distance to beacon + + for scanner.Scan() { + line := scanner.Text() + s, b, _ := strings.Cut(line, ": ") + sensor := getCoords(strings.Cut(strings.Trim(s, "Sensor at x="), ", y=")) + beacon := getCoords(strings.Cut(strings.Trim(b, "closest beacon is at x="), ", y=")) + dist := distance(sensor, beacon) + cave[sensor] = dist + } + // since there's only one of these holes in the search space, + // it must be just outside the maximum distance from a sensor + // it'll take far too long to search the entire cavern, after all + possibleCoords := []coord{} + for sensor, dist := range cave { + possibleCoords = append(possibleCoords, sensorHalo(sensor, dist)...) + } + for _, poss := range possibleCoords { + if poss.x < 0 || poss.y < 0 || poss.x > max || poss.y > max { + continue + } + hit := false + for sensor, dist := range cave { + if distance(sensor, poss) < dist { + hit = true + } + } + if !hit { + fmt.Println(poss.x*4000000 + poss.y) + return + } + } +}