2018 Complete!
This commit is contained in:
parent
0044574db3
commit
056ba2d484
55
2018/day25/constellation.go
Normal file
55
2018/day25/constellation.go
Normal file
@ -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
|
||||||
|
}
|
@ -2,146 +2,70 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"math"
|
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var grid *Grid
|
|
||||||
|
|
||||||
// Pt 1
|
|
||||||
// 431 too high
|
|
||||||
func main() {
|
func main() {
|
||||||
input := stdinToStringSlice()
|
inp := StdinToStringSlice()
|
||||||
grid = &Grid{}
|
fmt.Println(HotChocolatePortal(inp))
|
||||||
for _, v := range input {
|
|
||||||
grid.addPoint(v)
|
|
||||||
}
|
}
|
||||||
last := len(grid.constellations)
|
|
||||||
for grid.checkMerges() {
|
func HotChocolatePortal(input []string) int {
|
||||||
fmt.Println("++ merge ++ ", len(grid.constellations))
|
var constellations []Constellation
|
||||||
if len(grid.constellations) == last {
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
var found bool
|
||||||
|
for _, constellation := range constellations {
|
||||||
|
if constellation.Distance(c) <= 3 {
|
||||||
|
constellation.Add(c)
|
||||||
|
found = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
last = len(grid.constellations)
|
|
||||||
}
|
}
|
||||||
fmt.Println("Points:", len(grid.points))
|
if !found {
|
||||||
fmt.Println("Constellations:", len(grid.constellations))
|
constellations = append(constellations, NewConstellation(c))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Grid struct {
|
var nc []Constellation
|
||||||
points []*Pos
|
for i, a := range constellations {
|
||||||
constellations []*Constellation
|
merged := false
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Grid) checkMerges() bool {
|
for j, b := range constellations {
|
||||||
for ci, c := range g.constellations {
|
if i == j {
|
||||||
for _, p := range c.points {
|
|
||||||
for wrki, wrk := range g.constellations {
|
|
||||||
if wrki == ci {
|
|
||||||
continue
|
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) {
|
if b.CelestialDistance(a) <= 3 {
|
||||||
pts := strings.Split(inp, ",")
|
b.Merge(a)
|
||||||
pt := &Pos{
|
merged = true
|
||||||
x: atoi(pts[0]),
|
break
|
||||||
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 {
|
if !merged {
|
||||||
fmt.Println(" Merging", c1Idx, c2Idx)
|
nc = append(nc, a)
|
||||||
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 {
|
return len(nc)
|
||||||
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 {
|
func abs(num int) int {
|
||||||
points []*Pos
|
if num < 0 {
|
||||||
|
return num * -1
|
||||||
|
}
|
||||||
|
return num
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Constellation) should(p *Pos) bool {
|
func StdinToStringSlice() []string {
|
||||||
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
|
var input []string
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
@ -149,12 +73,3 @@ func stdinToStringSlice() []string {
|
|||||||
}
|
}
|
||||||
return input
|
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
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user