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 }