161 lines
3.0 KiB
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
|
|
}
|