day 15
This commit is contained in:
parent
b705b68051
commit
f00d2805fd
161
15/main.go
Normal file
161
15/main.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user