2018-12-06 19:42:05 +01:00
package main
import (
2018-12-06 23:48:18 +01:00
"fmt"
"io/ioutil"
"strconv"
"strings"
//"math"
2018-12-06 19:42:05 +01:00
)
// tfw no built-in abs() for int
2018-12-06 23:48:18 +01:00
func Abs ( x int ) int {
if x > 0 {
return x
}
return x * - 1
2018-12-06 19:42:05 +01:00
}
func getBounds ( nodes [ ] Node ) Point {
2018-12-06 23:48:18 +01:00
outPoint := Point { X : 0 , Y : 0 }
for _ , n := range nodes {
if n . Pos . X > outPoint . X {
outPoint . X = n . Pos . X
}
if n . Pos . Y > outPoint . Y {
outPoint . Y = n . Pos . Y
}
}
// Make sure no points are directly touching the edges
outPoint . X ++
outPoint . Y ++
return outPoint
2018-12-06 19:42:05 +01:00
}
type Point struct {
2018-12-06 23:48:18 +01:00
X int
Y int
2018-12-06 19:42:05 +01:00
}
type Node struct {
2018-12-06 23:48:18 +01:00
ID byte
Pos Point
Size int
2018-12-06 19:42:05 +01:00
}
func ParseInput ( input string ) [ ] Node {
2018-12-06 23:48:18 +01:00
lines := strings . Split ( input , "\n" )
output := make ( [ ] Node , len ( lines ) )
for i , line := range lines {
coords := strings . Split ( line , ", " )
x , _ := strconv . Atoi ( coords [ 1 ] )
y , _ := strconv . Atoi ( coords [ 0 ] )
node := Node { ID : byte ( i ) , Pos : Point { X : x , Y : y } , Size : 0 }
output [ i ] = node
}
return output
}
func FindClosest ( p Point , nodes [ ] Node ) byte {
var closest Node
minD := 9999999
tied := false
for _ , node := range nodes {
d := ManhattanDistance ( node . Pos , p )
if d < minD {
minD = d
closest = node
tied = false
} else if d == minD {
tied = true
}
}
if tied {
return byte ( 255 )
}
return closest . ID
}
func DistanceToAll ( p Point , nodes [ ] Node ) int {
total := 0
for _ , node := range nodes {
total += ManhattanDistance ( p , node . Pos )
}
return total
}
func CalculateTerritory ( n Node , fields [ ] [ ] byte ) int {
marker := n . ID
size := 0
boundX := len ( fields ) - 1
boundY := len ( fields [ 0 ] ) - 1
for x , outer := range fields {
for y := range outer {
if fields [ x ] [ y ] == marker {
if x == 0 || y == 0 || x == boundX || y == boundY {
return 0
}
size ++
}
}
}
return size
2018-12-06 19:42:05 +01:00
}
func ManhattanDistance ( first Point , second Point ) int {
2018-12-06 23:48:18 +01:00
return Abs ( first . X - second . X ) + Abs ( first . Y - second . Y )
2018-12-06 19:42:05 +01:00
}
func main ( ) {
2018-12-06 23:48:18 +01:00
inFile , _ := ioutil . ReadFile ( "input" )
inString := string ( inFile )
2018-12-06 19:42:05 +01:00
2018-12-06 23:48:18 +01:00
points := ParseInput ( inString )
bounds := getBounds ( points )
fields := make ( [ ] [ ] byte , bounds . X )
for i := range fields {
fields [ i ] = make ( [ ] byte , bounds . Y )
}
2018-12-06 19:42:05 +01:00
2018-12-06 23:48:18 +01:00
// Part 1
for x , outer := range fields {
for y := range outer {
fields [ x ] [ y ] = FindClosest ( Point { X : x , Y : y } , points )
}
}
for i , node := range points {
points [ i ] . Size = CalculateTerritory ( node , fields )
}
var biggest Node
biggest . Size = 0
for _ , node := range points {
if node . Size > biggest . Size {
biggest = node
}
fields [ node . Pos . X ] [ node . Pos . Y ] = node . ID + 100
}
fmt . Println ( biggest )
// Part 2
closeEnough := 0
for x , outer := range fields {
for y := range outer {
if DistanceToAll ( Point { X : x , Y : y } , points ) < 10000 {
closeEnough ++
}
}
}
fmt . Println ( closeEnough )
}