diff options
Diffstat (limited to 'day23/main.go')
-rw-r--r-- | day23/main.go | 144 |
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 +} |