This commit is contained in:
2022-12-23 19:45:56 -08:00
commit 8792e5275a
77 changed files with 31154 additions and 0 deletions

182
solutions/day15/day15.go Normal file
View File

@@ -0,0 +1,182 @@
package day15
import (
"bufio"
"fmt"
"os"
"strconv"
)
type Point struct {
x int
y int
}
func pointDistance(a Point, b Point) int {
return diff(a.x, b.x) + diff(a.y, b.y)
}
func diff(a int, b int) int {
if a > b {
return a - b
} else {
return b - a
}
}
type Sensor struct {
location Point
distance int
}
func parseLine(line string) (sensor Sensor, beacon Point) {
var sensorX int
var sensorY int
var beaconX int
var beaconY int
fmt.Sscanf(line, "Sensor at x=%d, y=%d: closest beacon is at x=%d, y=%d", &sensorX, &sensorY, &beaconX, &beaconY)
sensorLoc := Point{sensorX, sensorY}
beacon = Point{beaconX, beaconY}
distance := pointDistance(sensorLoc, beacon)
sensor = Sensor{sensorLoc, distance}
return
}
func isBeacon(x int, y int, beacons []Point) bool {
for _, beacon := range beacons {
if beacon.x == x && beacon.y == y {
return true
}
}
return false
}
func inSensorRange(x int, y int, sensors []Sensor) *Sensor {
point := Point{x, y}
for _, sensor := range sensors {
distance := pointDistance(point, sensor.location)
if distance <= sensor.distance {
return &sensor
}
}
return nil
}
func leftmostPoint(sensors []Sensor) int {
leftmost := 0
for _, sensor := range sensors {
candidate := sensor.location.x - sensor.distance
if candidate < leftmost {
leftmost = candidate
}
}
return leftmost
}
func rightmostPoint(sensors []Sensor) int {
rightmost := 0
for _, sensor := range sensors {
candidate := sensor.location.x + sensor.distance
if candidate > rightmost {
rightmost = candidate
}
}
return rightmost
}
func addLinePoints(pointSet *[]Point, start Point, end Point) {
offsetX := 1
offsetY := 1
if end.x < start.x {
offsetX = -1
}
if end.y < start.y {
offsetY = -1
}
for x, y := start.x, start.y; y != end.y; x, y = x+offsetX, y+offsetY {
*pointSet = append(*pointSet, Point{x, y})
}
}
func addEdgePoints(pointSet *[]Point, sensor Sensor) {
distance := sensor.distance + 1
top := Point{sensor.location.x, sensor.location.y - distance}
right := Point{sensor.location.x + distance, sensor.location.y}
bottom := Point{sensor.location.x, sensor.location.y + distance}
left := Point{sensor.location.x - distance, sensor.location.y}
addLinePoints(pointSet, top, right)
addLinePoints(pointSet, right, bottom)
addLinePoints(pointSet, bottom, left)
addLinePoints(pointSet, left, top)
}
func Run(filename string, yStr string, maxCoordStr string) {
y, err := strconv.Atoi(yStr)
if err != nil {
fmt.Println("PANIC: bad y argument", yStr)
return
}
maxCoord, err := strconv.Atoi(maxCoordStr)
if err != nil {
fmt.Println("PANIC: bad y argument", maxCoordStr)
return
}
file, err := os.Open(filename)
if err != nil {
fmt.Println("Error opening file:", err)
return
}
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
sensors := []Sensor{}
beacons := []Point{}
for scanner.Scan() {
line := scanner.Text()
sensor, beacon := parseLine(line)
sensors = append(sensors, sensor)
beacons = append(beacons, beacon)
}
file.Close()
fmt.Println(sensors)
count := 0
for x := leftmostPoint(sensors); x <= rightmostPoint(sensors); x++ {
if isBeacon(x, y, beacons) {
continue
}
if inSensorRange(x, y, sensors) != nil {
count += 1
}
}
fmt.Println("Beacons couldn't be in", count, "places on line", y)
candidates := []Point{}
for _, sensor := range sensors {
addEdgePoints(&candidates, sensor)
}
for _, candidate := range candidates {
if candidate.x >= 0 && candidate.y >= 0 && candidate.x <= maxCoord && candidate.y <= maxCoord {
closestSensor := inSensorRange(candidate.x, candidate.y, sensors)
if closestSensor == nil {
fmt.Printf("Found possible beacon location at (%d, %d). Frequency value is %d\n", candidate.x, candidate.y, candidate.x*4000000+candidate.y)
}
}
}
}