Files
advent-of-code-go/2018/day06/main.go
T

135 lines
2.9 KiB
Go

package main
import (
"flag"
"fmt"
"math"
"strings"
"github.com/alexchao26/advent-of-code-go/cast"
"github.com/alexchao26/advent-of-code-go/mathy"
"github.com/alexchao26/advent-of-code-go/util"
)
func main() {
var part int
flag.IntVar(&part, "part", 1, "part 1 or 2")
flag.Parse()
fmt.Println("Running part", part)
if part == 1 {
ans := part1(util.ReadFile("./input.txt"))
fmt.Println("Output:", ans)
} else {
ans := part2(util.ReadFile("./input.txt"), 10000)
fmt.Println("Output:", ans)
}
}
func part1(input string) int {
coords := parseInputCoords(input)
boundLeft, boundRight, boundTop, boundBottom := getBounds(coords)
// maps coordinates to the number (count) of cells that they are closest too
coordsToMinDistanceCounts := map[[2]int]int{}
for r := boundTop; r <= boundBottom; r++ {
for c := boundLeft; c <= boundRight; c++ {
bestManhattan := math.MaxInt16
var coordsToBest [2]int
distCounts := map[int]int{} // dedeupe equidistant cells
for _, coord := range coords {
man := mathy.ManhattanDistance(r, c, coord[0], coord[1])
if man <= bestManhattan {
bestManhattan = man
coordsToBest = coord
distCounts[bestManhattan]++
}
}
// do not increment anything if there were two equidistant coords
if distCounts[bestManhattan] == 1 {
coordsToMinDistanceCounts[coordsToBest]++
}
}
}
var largest int
for coord, val := range coordsToMinDistanceCounts {
// exclude edges
if coord[0] == boundTop || coord[0] == boundBottom {
continue
}
if coord[1] == boundLeft || coord[1] == boundRight {
continue
}
if val > largest {
largest = val
}
}
return largest
}
func part2(input string, dist int) int {
coords := parseInputCoords(input)
boundLeft, boundRight, boundTop, boundBottom := getBounds(coords)
coordsToTotalDist := map[[2]int]int{}
var area int
for r := boundTop; r <= boundBottom; r++ {
for c := boundLeft; c <= boundRight; c++ {
point := [2]int{r, c}
for _, coord := range coords {
coordsToTotalDist[point] += mathy.ManhattanDistance(point[0], point[1], coord[0], coord[1])
}
if coordsToTotalDist[point] < dist {
area++
}
}
}
return area
}
func parseInputCoords(input string) [][2]int {
lines := strings.Split(input, "\n")
coords := [][2]int{} // [row, col]
for _, l := range lines {
c := strings.Split(l, ", ")
if len(c) == 2 {
coords = append(coords, [2]int{
cast.ToInt(c[0]),
cast.ToInt(c[1]),
})
}
}
return coords
}
func getBounds(coords [][2]int) (left int, right int, top int, bottom int) {
var (
boundLeft = math.MaxInt16
boundRight = -math.MaxInt16
boundTop = math.MaxInt16
boundBottom = -math.MaxInt16
)
for _, c := range coords {
if c[0] < boundTop {
boundTop = c[0]
}
if c[0] > boundBottom {
boundBottom = c[0]
}
if c[1] < boundLeft {
boundLeft = c[1]
}
if c[1] > boundRight {
boundRight = c[1]
}
}
return boundLeft, boundRight, boundTop, boundBottom
}