summaryrefslogtreecommitdiff
path: root/day23/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'day23/main.go')
-rw-r--r--day23/main.go144
1 files changed, 144 insertions, 0 deletions
diff --git a/day23/main.go b/day23/main.go
new file mode 100644
index 0000000..81cc6a0
--- /dev/null
+++ b/day23/main.go
@@ -0,0 +1,144 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "sort"
+ "strings"
+)
+
+func main() {
+ fmt.Println(part1(readData("example.txt")), 7)
+ fmt.Println(part1(readData("data.txt")), 1043)
+ fmt.Println("co,de,ka,ta")
+ fmt.Println(part2(readData("example.txt")))
+ fmt.Println("ai,bk,dc,dx,fo,gx,hk,kd,os,uz,xn,yk,zs")
+ fmt.Println(part2(readData("data.txt")))
+}
+
+const SIZE = 26 * 26
+
+func buildAdjacency(pairs [][2]int) [][]bool {
+ matrix := make([][]bool, SIZE)
+ for a := range matrix {
+ matrix[a] = make([]bool, SIZE)
+ }
+
+ for _, p := range pairs {
+ matrix[p[0]][p[1]] = true
+ matrix[p[1]][p[0]] = true
+ }
+
+ return matrix
+}
+
+func part1(pairs [][2]int) (count int) {
+ matrix := buildAdjacency(pairs)
+ triples := make(map[[3]int]bool)
+
+ for a := range SIZE {
+ connectedToA := make([]int, 0)
+ for b := a + 1; b < SIZE; b++ {
+ if matrix[a][b] {
+ connectedToA = append(connectedToA, b)
+ }
+ }
+ for ib, b := range connectedToA {
+ for ic := ib + 1; ic < len(connectedToA); ic++ {
+ c := connectedToA[ic]
+ if matrix[b][c] {
+ sortTriple(&a, &b, &c)
+ triples[[3]int{a, b, c}] = true
+ }
+ }
+ }
+ }
+
+ for t := range triples {
+ if containsT(t[0]) || containsT(t[1]) || containsT(t[2]) {
+ count++
+ }
+ }
+
+ return count
+}
+
+func part2(pairs [][2]int) string {
+ matrix := buildAdjacency(pairs)
+ sets := [][]int{}
+
+ for a := range SIZE {
+ isInAnySet := false
+ for i, set := range sets {
+ connectedToAll := true
+ for _, other := range set {
+ if !matrix[a][other] {
+ connectedToAll = false
+ break
+ }
+ }
+ if connectedToAll {
+ sets[i] = append(set, a)
+ isInAnySet = true
+ }
+ }
+ if !isInAnySet {
+ sets = append(sets, []int{a})
+ }
+ }
+
+ maxSet := []int{}
+ for _, set := range sets {
+ if len(set) > len(maxSet) {
+ maxSet = set
+ }
+ }
+
+ ids := make([]string, 0, len(maxSet))
+ for _, id := range maxSet {
+ ids = append(ids, numToId(id))
+ }
+
+ sort.Sort(sort.StringSlice(ids))
+ return strings.Join(ids, ",")
+}
+
+func containsT(x int) bool {
+ const MIN = int('t'-'a') * 26
+ const MAX = MIN + 25
+ return x >= MIN && x <= MAX
+}
+
+func sortTriple(a, b, c *int) {
+ maybeSwap := func(a, b *int) {
+ if *a > *b {
+ *a, *b = *b, *a
+ }
+ }
+ maybeSwap(a, b)
+ maybeSwap(b, c)
+ maybeSwap(a, b)
+ maybeSwap(b, c)
+}
+
+func idToNum(s string) int {
+ return int(s[0]-'a')*26 + int(s[1]-'a')
+}
+
+func numToId(id int) string {
+ return string([]byte{byte(id/26 + 'a'), byte(id%26 + 'a')})
+}
+
+func readData(fileName string) (pairs [][2]int) {
+ fp, _ := os.Open(fileName)
+ scanner := bufio.NewScanner(fp)
+
+ for scanner.Scan() {
+ line := scanner.Text()
+ pair := [2]int{idToNum(line[0:2]), idToNum(line[3:5])}
+ pairs = append(pairs, pair)
+ }
+
+ return
+}