From 15c41ba2279e8895dbf8e42a3518d59d33ed2419 Mon Sep 17 00:00:00 2001 From: alexchao26 Date: Sat, 12 Dec 2020 21:23:40 -0500 Subject: [PATCH] 2018-day25: UGLY graph grouping solution...but 2018 completed! --- 2018/day25/main.go | 97 +++++++++++++++++++++++++++++++++++++++++ 2018/day25/main_test.go | 64 +++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 2018/day25/main.go create mode 100644 2018/day25/main_test.go diff --git a/2018/day25/main.go b/2018/day25/main.go new file mode 100644 index 0000000..bcd113d --- /dev/null +++ b/2018/day25/main.go @@ -0,0 +1,97 @@ +package main + +import ( + "flag" + "fmt" + "strings" + + "github.com/alexchao26/advent-of-code-go/util" +) + +func main() { + var part int + flag.IntVar(&part, "part", 1, "part 1 or 2") + flag.Parse() + fmt.Println("Running part", part) + + if part == 1 { + ans := part1(util.ReadFile("./input.txt")) + fmt.Println("Output:", ans) + } else { + panic("no part 2 :P") + } +} + +func part1(input string) int { + allCoords := parseInput(input) + + constellations := [][][4]int{} + + for _, iterCoord := range allCoords { + // check which constellations this coordinate is in range of + indicesWithinRange := []int{} + for constIndex, constellation := range constellations { + for _, constCoord := range constellation { + if manhattanDistance(constCoord, iterCoord) <= 3 { + indicesWithinRange = append(indicesWithinRange, constIndex) + break + } + } + } + + // if no existing constellations are within range, append a new one with + // just this current coordinate + if len(indicesWithinRange) == 0 { + constellations = append(constellations, [][4]int{iterCoord}) + } else { + // otherwise merge all constellations together (into the first one) + // add the current node + // then remove any other constellations that were merged into #1 + firstIndex := indicesWithinRange[0] + for i, indexToMerge := range indicesWithinRange { + if i != 0 { + current := constellations[indexToMerge] + constellations[firstIndex] = append(constellations[firstIndex], current...) + } + } + constellations[firstIndex] = append(constellations[firstIndex], iterCoord) + + // remove all but the first constellation, in reverse order b/c + // using this method for removal affects the end of the slice, and + // in some cases that may be the element that we want to remove + for i := len(indicesWithinRange) - 1; i > 0; i-- { + constIndex := indicesWithinRange[i] + lastIndex := len(constellations) - 1 + constellations[constIndex] = constellations[lastIndex] + constellations = constellations[:lastIndex] + } + } + } + + return len(constellations) +} + +func parseInput(input string) [][4]int { + lines := strings.Split(input, "\n") + allCoords := make([][4]int, len(lines)) + for i, l := range lines { + newCoord := [4]int{} + fmt.Sscanf(l, "%d,%d,%d,%d", &newCoord[0], &newCoord[1], &newCoord[2], &newCoord[3]) + + allCoords[i] = newCoord + } + + return allCoords +} + +func manhattanDistance(one, two [4]int) int { + var sum int + for i := range one { + diff := one[i] - two[i] + if diff < 0 { + diff *= -1 + } + sum += diff + } + return sum +} diff --git a/2018/day25/main_test.go b/2018/day25/main_test.go new file mode 100644 index 0000000..b6aa1a0 --- /dev/null +++ b/2018/day25/main_test.go @@ -0,0 +1,64 @@ +package main + +import ( + "testing" + + "github.com/alexchao26/advent-of-code-go/util" +) + +var tests1 = []struct { + name string + want int + input string + // add extra args if needed +}{ + {"example 2", 2, `0,0,0,0 +3,0,0,0 +0,3,0,0 +0,0,3,0 +0,0,0,3 +0,0,0,6 +9,0,0,0 +12,0,0,0`}, + {"example 3", 3, `1,-1,0,1 +2,0,-1,0 +3,2,-1,0 +0,0,3,1 +0,0,-1,-1 +2,3,-2,0 +-2,2,0,0 +2,-2,0,-1 +1,-1,0,-1 +3,2,0,2`}, + {"example 4", 4, `-1,2,2,0 +0,0,2,-2 +0,0,0,-2 +-1,2,0,0 +-2,-2,-2,2 +3,0,2,-1 +-1,3,2,2 +-1,0,-1,0 +0,2,1,-2 +3,0,0,0`}, + {"example 8", 8, `1,-1,-1,-2 +-2,-2,0,1 +0,2,1,3 +-2,3,-2,1 +0,2,3,-2 +-1,-1,1,-2 +0,-2,-1,0 +-2,2,3,-1 +1,2,2,0 +-1,-2,0,-2`}, + {"actual", 422, util.ReadFile("input.txt")}, +} + +func TestPart1(t *testing.T) { + for _, tt := range tests1 { + t.Run(tt.name, func(t *testing.T) { + if got := part1(tt.input); got != tt.want { + t.Errorf("part1() = %v, want %v", got, tt.want) + } + }) + } +}