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