adventofcode/2018/day25/day25.go

161 lines
3.0 KiB
Go

package main
import (
"bufio"
"errors"
"fmt"
"log"
"math"
"os"
"strconv"
"strings"
)
var grid *Grid
// Pt 1
// 431 too high
func main() {
input := stdinToStringSlice()
grid = &Grid{}
for _, v := range input {
grid.addPoint(v)
}
last := len(grid.constellations)
for grid.checkMerges() {
fmt.Println("++ merge ++ ", len(grid.constellations))
if len(grid.constellations) == last {
break
}
last = len(grid.constellations)
}
fmt.Println("Points:", len(grid.points))
fmt.Println("Constellations:", len(grid.constellations))
}
type Grid struct {
points []*Pos
constellations []*Constellation
}
func (g *Grid) checkMerges() bool {
for ci, c := range g.constellations {
for _, p := range c.points {
for wrki, wrk := range g.constellations {
if wrki == ci {
continue
}
if wrk.should(p) {
g.merge(ci, wrki)
g.remove(wrki)
return true
}
}
}
}
fmt.Println("Nothing merged")
return false
}
func (g *Grid) addPoint(inp string) {
pts := strings.Split(inp, ",")
pt := &Pos{
x: atoi(pts[0]),
y: atoi(pts[1]),
z: atoi(pts[2]),
t: atoi(pts[3]),
}
g.points = append(g.points, pt)
// Check if this point is within 3 from any other points
cIdx := -1
var mergedIdx []int
for i, v := range g.constellations {
if v.should(pt) {
if cIdx >= 0 {
g.merge(cIdx, i)
mergedIdx = append(mergedIdx, i)
} else {
cIdx = i
g.constellations[cIdx].add(pt)
}
}
}
for i := range mergedIdx {
g.remove(i)
}
if cIdx == -1 {
c := &Constellation{}
c.add(pt)
g.constellations = append(g.constellations, c)
}
}
func (g *Grid) merge(c1Idx, c2Idx int) error {
fmt.Println(" Merging", c1Idx, c2Idx)
if c1Idx >= len(g.constellations) || c2Idx >= len(g.constellations) {
return errors.New("Invalid Constellation Index")
}
for _, v := range g.constellations[c2Idx].points {
g.constellations[c1Idx].add(v)
}
return nil
}
func (g *Grid) remove(remIdx int) error {
if remIdx >= len(g.constellations) {
return errors.New("Invalid Constellation Index")
}
g.constellations = append(g.constellations[:remIdx], g.constellations[remIdx+1:]...)
return nil
}
type Constellation struct {
points []*Pos
}
func (c *Constellation) should(p *Pos) bool {
for _, v := range c.points {
if v.to(p) <= 3 {
return true
}
}
return false
}
func (c *Constellation) add(p *Pos) {
p.constellation = c
c.points = append(c.points, p)
}
type Pos struct {
x, y, z, t int
constellation *Constellation
}
func (p *Pos) to(p2 *Pos) int {
xs := math.Abs(float64(p.x) - float64(p2.x))
ys := math.Abs(float64(p.y) - float64(p2.y))
zs := math.Abs(float64(p.z) - float64(p2.z))
ts := math.Abs(float64(p.t) - float64(p2.t))
return int(xs + ys + zs + ts)
}
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: " + i)
}
return ret
}