2018 Day 06 Complete
This commit is contained in:
185
2018/day06/day06.go
Normal file
185
2018/day06/day06.go
Normal file
@@ -0,0 +1,185 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const MaxInt = int(^uint(0) >> 1)
|
||||
|
||||
func main() {
|
||||
inp := StdinToStringSlice()
|
||||
start(inp)
|
||||
part1()
|
||||
part2()
|
||||
}
|
||||
|
||||
var points []RegionPos
|
||||
var boundaries []RegionPos
|
||||
var allPoints []RegionPos
|
||||
var maxX, maxY, minX, minY int
|
||||
|
||||
func start(inp []string) {
|
||||
maxX, maxY = 0, 0
|
||||
minX, minY = MaxInt, MaxInt
|
||||
|
||||
for _, v := range inp {
|
||||
pts := strings.Split(v, ", ")
|
||||
x, y := Atoi(pts[0]), Atoi(pts[1])
|
||||
p := RegionPos{x: x, y: y}
|
||||
points = append(points, p)
|
||||
if x < minX {
|
||||
minX = x
|
||||
}
|
||||
if x > maxX {
|
||||
maxX = x
|
||||
}
|
||||
if y < minY {
|
||||
minY = y
|
||||
}
|
||||
if y > maxY {
|
||||
maxY = y
|
||||
}
|
||||
}
|
||||
// Find the points that are the closest to the boundaries
|
||||
for x := minX; x <= maxX; x++ {
|
||||
boundaries = append(boundaries, *NewRegionPos(x, minY))
|
||||
boundaries = append(boundaries, *NewRegionPos(x, maxY))
|
||||
}
|
||||
for y := minY; y <= maxY; y++ {
|
||||
boundaries = append(boundaries, *NewRegionPos(minX, y))
|
||||
boundaries = append(boundaries, *NewRegionPos(maxX, y))
|
||||
}
|
||||
for i := range boundaries {
|
||||
closest := boundaries[i].findClosest(points)
|
||||
if len(closest) == 1 {
|
||||
for j := range points {
|
||||
if points[j].x == closest[0].x && points[j].y == closest[0].y {
|
||||
points[j].ignored = true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
boundaries[i].ignored = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func part1() {
|
||||
for x := minX; x <= maxX; x++ {
|
||||
for y := minY; y <= maxY; y++ {
|
||||
p := NewRegionPos(x, y)
|
||||
closest := p.findClosest(points)
|
||||
if len(closest) == 1 {
|
||||
c := closest[0]
|
||||
for i := range points {
|
||||
if points[i].ignored {
|
||||
continue
|
||||
}
|
||||
if points[i].x == c.x && points[i].y == c.y {
|
||||
points[i].regionSize++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var largestSize int
|
||||
for _, v := range points {
|
||||
if !v.ignored {
|
||||
if v.regionSize > largestSize {
|
||||
largestSize = v.regionSize
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println("= Part 1 =")
|
||||
fmt.Println(largestSize)
|
||||
}
|
||||
|
||||
func part2() {
|
||||
minDistance := 10000
|
||||
|
||||
var regionCount int
|
||||
for y := minY - minDistance; y <= maxY+minDistance; y++ {
|
||||
for x := minX - minDistance; x <= maxX+minDistance; x++ {
|
||||
p := NewRegionPos(x, y)
|
||||
if p.sumOfDistances(minDistance, points) < minDistance {
|
||||
regionCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println("= Part 2 =")
|
||||
fmt.Println(regionCount)
|
||||
}
|
||||
|
||||
func manhattanDistance(x1, y1, x2, y2 int) int {
|
||||
return int(math.Abs(float64(x1)-float64(x2)) + math.Abs(float64(y1)-float64(y2)))
|
||||
}
|
||||
|
||||
type RegionPos struct {
|
||||
x, y int
|
||||
regionSize int
|
||||
closestPos *RegionPos
|
||||
ignored bool
|
||||
}
|
||||
|
||||
func NewRegionPos(x, y int) *RegionPos {
|
||||
b := &RegionPos{}
|
||||
b.x = x
|
||||
b.y = y
|
||||
return b
|
||||
}
|
||||
|
||||
func (p *RegionPos) distanceToPos(o *RegionPos) int {
|
||||
return manhattanDistance(p.x, p.y, o.x, o.y)
|
||||
}
|
||||
|
||||
func (b *RegionPos) sumOfDistances(d int, list []RegionPos) int {
|
||||
var ret int
|
||||
for _, p := range list {
|
||||
ret += b.distanceToPos(&p)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (b *RegionPos) findClosest(list []RegionPos) []RegionPos {
|
||||
var ret []RegionPos
|
||||
minD := MaxInt
|
||||
for _, p := range list {
|
||||
test := b.distanceToPos(&p)
|
||||
if test < minD {
|
||||
minD = test
|
||||
ret = ret[:0]
|
||||
ret = append(ret, p)
|
||||
} else if test == minD {
|
||||
ret = append(ret, p)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (b *RegionPos) string() string {
|
||||
return fmt.Sprintf("%d;%d", b.x, b.y)
|
||||
}
|
||||
|
||||
func StdinToStringSlice() []string {
|
||||
var input []string
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
input = append(input, scanner.Text())
|
||||
}
|
||||
return input
|
||||
}
|
||||
|
||||
func Atoi(i string) int {
|
||||
var ret int
|
||||
var err error
|
||||
if ret, err = strconv.Atoi(i); err != nil {
|
||||
log.Fatal("Invalid Atoi")
|
||||
}
|
||||
return ret
|
||||
}
|
||||
Reference in New Issue
Block a user