145 lines
2.6 KiB
Go
145 lines
2.6 KiB
Go
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
|
|
}
|