Files
aoc2024/day23/main.go
2024-12-23 23:33:31 +01:00

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
}