This commit is contained in:
David 2022-12-26 17:29:38 -07:00
parent b705b68051
commit f00d2805fd

161
15/main.go Normal file
View File

@ -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
}
}
}