Day 6 part 1.
This commit is contained in:
parent
6185736ef6
commit
0c96d7dded
23
2018/day06-1.go
Normal file
23
2018/day06-1.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"internal/coords"
|
||||||
|
"internal/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
data := util.ReadInput()
|
||||||
|
points := coords.ParsePoints(data)
|
||||||
|
|
||||||
|
coords.ComputeRectilinearAreas(points)
|
||||||
|
|
||||||
|
biggest := points[0]
|
||||||
|
for _, point := range points {
|
||||||
|
if point.RectArea > biggest.RectArea {
|
||||||
|
biggest = point
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println(biggest.RectArea)
|
||||||
|
}
|
111
2018/internal/coords/coords.go
Normal file
111
2018/internal/coords/coords.go
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
package coords
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Point struct {
|
||||||
|
X int
|
||||||
|
Y int
|
||||||
|
RectArea int
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParsePoints(data []string) []*Point {
|
||||||
|
points := []*Point{}
|
||||||
|
|
||||||
|
for _, pointInfo := range data {
|
||||||
|
components := strings.Split(pointInfo, ", ")
|
||||||
|
x, _ := strconv.Atoi(components[0])
|
||||||
|
y, _ := strconv.Atoi(components[1])
|
||||||
|
points = append(points, &Point{
|
||||||
|
X: x,
|
||||||
|
Y: y,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return points
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutates the passed-in data in-place, computing the rectilinear
|
||||||
|
// area for all points within the space bounded by (0,0) and the points themselves.
|
||||||
|
// Sets the area of the 4 corner-most points (which definitionally must have
|
||||||
|
// unbounded areas) to -1
|
||||||
|
func ComputeRectilinearAreas(data []*Point) {
|
||||||
|
// first we find the bounds
|
||||||
|
maxX := 0
|
||||||
|
maxY := 0
|
||||||
|
for _, point := range data {
|
||||||
|
if point.X > maxX {
|
||||||
|
maxX = point.X
|
||||||
|
}
|
||||||
|
if point.Y > maxY {
|
||||||
|
maxY = point.Y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now for each integer point in our range, we compute the distance to each
|
||||||
|
// point. We save the closest point and its distance, then:
|
||||||
|
// 1. If there are two or more identically closest points, we do nothing.
|
||||||
|
// 2. Otherwise, we increment RectArea for the closest point.
|
||||||
|
for x := -maxX; x <= maxX*2; x++ {
|
||||||
|
for y := -maxY; y <= maxY*2; y++ {
|
||||||
|
closest := FindClosest(data, &Point{X: x, Y: y})
|
||||||
|
if closest == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
closest.RectArea++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we find any unbounded points and set their areas to the sentinel
|
||||||
|
// value
|
||||||
|
DetectUnboundedPoints(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindClosest(data []*Point, point *Point) *Point {
|
||||||
|
closest := data[0]
|
||||||
|
distance := computeDistance(data[0], point)
|
||||||
|
|
||||||
|
for i := 1; i < len(data); i++ {
|
||||||
|
candidate := data[i]
|
||||||
|
newDistance := computeDistance(candidate, point)
|
||||||
|
|
||||||
|
if newDistance < distance {
|
||||||
|
closest = candidate
|
||||||
|
distance = newDistance
|
||||||
|
} else if newDistance == distance {
|
||||||
|
closest = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return closest
|
||||||
|
}
|
||||||
|
|
||||||
|
func DetectUnboundedPoints(data []*Point) {
|
||||||
|
for _, candidate := range data {
|
||||||
|
// look in each direction
|
||||||
|
up := FindClosest(data, &Point{X: candidate.X, Y: candidate.Y + 1000000})
|
||||||
|
down := FindClosest(data, &Point{X: candidate.X, Y: candidate.Y - 1000000})
|
||||||
|
left := FindClosest(data, &Point{X: candidate.X + 1000000, Y: candidate.Y})
|
||||||
|
right := FindClosest(data, &Point{X: candidate.X - 1000000, Y: candidate.Y})
|
||||||
|
|
||||||
|
// if any of those points are closest to our point, we're unbounded
|
||||||
|
if up == candidate || down == candidate ||
|
||||||
|
left == candidate || right == candidate {
|
||||||
|
candidate.RectArea = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func computeDistance(p1 *Point, p2 *Point) int {
|
||||||
|
return abs(p2.Y-p1.Y) + abs(p2.X-p1.X)
|
||||||
|
}
|
||||||
|
|
||||||
|
func abs(x int) int {
|
||||||
|
if x < 0 {
|
||||||
|
return -x
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user