diff --git a/2018/day25/constellation.go b/2018/day25/constellation.go new file mode 100644 index 0000000..c8b7498 --- /dev/null +++ b/2018/day25/constellation.go @@ -0,0 +1,55 @@ +package main + +import "math" + +type Coordinate [4]int + +func (c Coordinate) Distance(b Coordinate) int { + sum := 0 + for i := 0; i < 4; i++ { + sum += abs(c[i] - b[i]) + } + return sum +} + +type Constellation map[Coordinate]struct{} + +func (c Constellation) Distance(b Coordinate) int { + shortestDistance := math.MaxInt64 + + for p := range c { + if p.Distance(b) < shortestDistance { + shortestDistance = p.Distance(b) + } + } + + return shortestDistance +} + +func (c Constellation) CelestialDistance(b Constellation) int { + shortestDistance := math.MaxInt64 + + for p := range c { + if b.Distance(p) < shortestDistance { + shortestDistance = b.Distance(p) + } + } + + return shortestDistance +} + +func (c Constellation) Add(b Coordinate) { + c[b] = struct{}{} +} + +func (c Constellation) Merge(b Constellation) { + for p := range b { + c[p] = struct{}{} + delete(b, p) + } +} + +func NewConstellation(b Coordinate) Constellation { + c := Constellation{b: struct{}{}} + return c +} diff --git a/2018/day25/day25.go b/2018/day25/day25.go index 7d57386..94bebbc 100644 --- a/2018/day25/day25.go +++ b/2018/day25/day25.go @@ -2,146 +2,70 @@ 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 + inp := StdinToStringSlice() + fmt.Println(HotChocolatePortal(inp)) +} + +func HotChocolatePortal(input []string) int { + var constellations []Constellation + + for _, line := range input { + var c Coordinate + + if _, err := fmt.Sscanf(line, "%d,%d,%d,%d", &c[0], &c[1], &c[2], &c[3]); err != nil { + panic(err) } - 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 - } + var found bool + for _, constellation := range constellations { + if constellation.Distance(c) <= 3 { + constellation.Add(c) + found = true + break } } + if !found { + constellations = append(constellations, NewConstellation(c)) + } } - 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) + var nc []Constellation + for i, a := range constellations { + merged := false - // 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 j, b := range constellations { + if i == j { + continue + } + + if b.CelestialDistance(a) <= 3 { + b.Merge(a) + merged = true + break } } - } - 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 + if !merged { + nc = append(nc, a) } } - return false + + return len(nc) } -func (c *Constellation) add(p *Pos) { - p.constellation = c - c.points = append(c.points, p) +func abs(num int) int { + if num < 0 { + return num * -1 + } + return num } -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 { +func StdinToStringSlice() []string { var input []string scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { @@ -149,12 +73,3 @@ func stdinToStringSlice() []string { } 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 -}