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 }