🌅
This commit is contained in:
182
solutions/day15/day15.go
Normal file
182
solutions/day15/day15.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user