2024 Day 23 Complete

This commit is contained in:
Brian Buller 2024-12-23 07:27:58 -06:00
parent 4f5898255b
commit 268d0a0141
4 changed files with 3663 additions and 0 deletions

3380
2024/day23/input Normal file

File diff suppressed because it is too large Load Diff

179
2024/day23/main.go Normal file
View File

@ -0,0 +1,179 @@
package main
import (
"fmt"
"sort"
"strings"
h "git.bullercodeworks.com/brian/adventofcode/helpers"
)
func main() {
inp := h.StdinToStringSlice()
part1(inp)
fmt.Println()
part2(inp)
}
func parseInput(inp []string) NetworkMap {
network := make(map[string]h.Set)
for _, l := range inp {
pts := strings.Split(l, "-")
if _, ok := network[pts[0]]; !ok {
network[pts[0]] = h.NewSet(1)
}
if _, ok := network[pts[1]]; !ok {
network[pts[1]] = h.NewSet(1)
}
network[pts[0]].Add(pts[1])
network[pts[1]].Add(pts[0])
}
return NewNetworkMap(network)
}
func part1(inp []string) {
nwk := parseInput(inp)
fmt.Println("# Part 1")
total := 0
wrk := nwk
for _, comp := range wrk.Comps {
conns := make([]string, 0, len(comp.Conns))
for name := range comp.Conns {
conns = append(conns, name)
total++
}
}
tris := wrk.FindTGroups()
fmt.Println(len(tris))
}
func part2(inp []string) {
nwk := parseInput(inp)
cnt := len(nwk.Comps)
wrk := h.NewSet(cnt)
for nm := range nwk.Comps {
wrk.Add(nm)
}
group := BronKerbosch(h.NewSet(cnt+1), wrk, h.NewSet(cnt+1), h.NewSet(0), nwk.Network)
fmt.Println("Group Size:", group.Size())
fmt.Println("Password:", strings.Join(group.ToSortedSlice(), ","))
}
func BronKerbosch(cl, chk, excl, kmax h.Set, graph map[string]h.Set) h.Set {
if chk.Empty() && excl.Empty() {
return cl
}
for vx := range chk {
vxSet := h.NewSetFromValues(vx)
vxConns := graph[vx]
nC := cl.Union(vxSet)
nWrk := chk.Intersection(vxConns)
if nC.Size()+nWrk.Size() <= kmax.Size() {
continue
}
newExcl := excl.Intersection(vxConns)
fC := BronKerbosch(nC, nWrk, newExcl, kmax, graph)
if fC.Size() > kmax.Size() {
kmax = fC
}
chk.Remove(vx)
excl.Add(vx)
}
return kmax
}
type NetworkMap struct {
Network map[string]h.Set
Comps map[string]*Comp
}
func NewNetworkMap(nwk map[string]h.Set) NetworkMap {
nm := NetworkMap{Network: nwk, Comps: make(map[string]*Comp)}
for name, conns := range nwk {
for conn := range conns {
nm.Connect(name, conn)
}
}
return nm
}
func (n *NetworkMap) Connect(c1, c2 string) {
n.GetComputer(c1).Connect(n.GetComputer(c2))
}
func (n *NetworkMap) GetComputer(nm string) *Comp {
if cm, ok := n.Comps[nm]; ok {
return cm
}
cm := NewComp(nm)
n.Comps[nm] = cm
return cm
}
func (n *NetworkMap) FindTGroups() map[Group]bool {
ret := make(map[Group]bool)
chk := make(map[string]bool)
for cn, comp := range n.Comps {
if chk[cn] {
continue
}
for nn, next := range comp.Conns {
friends := comp.FindFriends(next)
for _, friend := range friends {
if cn[0] == 't' || nn[0] == 't' || friend[0] == 't' {
grp := NewGroup([3]string{cn, nn, friend})
ret[grp] = true
}
}
chk[cn] = true
}
}
return ret
}
type Group struct {
Comps [3]string
}
func NewGroup(nodes [3]string) Group {
s := nodes[:]
sort.Strings(s)
return Group{Comps: [3]string{s[0], s[1], s[2]}}
}
func (g Group) String() string {
return fmt.Sprintf("%s-%s-%s", g.Comps[0], g.Comps[1], g.Comps[2])
}
type Comp struct {
Name string
Conns map[string]*Comp
}
func NewComp(n string) *Comp {
return &Comp{Name: n, Conns: make(map[string]*Comp)}
}
func (c *Comp) Connect(o *Comp) {
c.Conns[o.Name] = o
o.Conns[c.Name] = c
}
func (c *Comp) FindFriends(o *Comp) []string {
var friends []string
checked := make(map[string]bool)
for name := range c.Conns {
if name == c.Name || name == o.Name {
continue
}
if _, ok := checked[name]; ok {
continue
}
if _, ok := o.Conns[name]; !ok {
continue
}
friends = append(friends, name)
checked[name] = true
}
return friends
}

32
2024/day23/testinput Normal file
View File

@ -0,0 +1,32 @@
kh-tc
qp-kh
de-cg
ka-co
yn-aq
qp-ub
cg-tb
vc-aq
tb-ka
wh-tc
yn-cg
kh-ub
ta-co
de-co
tc-td
tb-wq
wh-td
ta-ka
td-qp
aq-cg
wq-ub
ub-vc
de-ta
wq-aq
wq-vc
wh-yn
ka-de
kh-ta
co-tc
wh-qp
tb-vc
td-yn

72
helpers/set.go Normal file
View File

@ -0,0 +1,72 @@
package aoc
import "slices"
type Set map[string]bool
func NewSet(l int) Set {
return make(map[string]bool, l)
}
func NewSetFromValues(v ...string) Set {
s := NewSet(len(v))
for _, val := range v {
s[val] = true
}
return s
}
func (s Set) Add(nm string) {
s[nm] = true
}
func (s Set) Remove(nm string) {
delete(s, nm)
}
func (s Set) Contains(nm string) bool {
_, ok := s[nm]
return ok
}
func (s Set) Empty() bool {
return len(s) == 0
}
func (s Set) Size() int {
return len(s)
}
func (s Set) Intersection(o Set) Set {
smallest, toCheck := s, o
if o.Size() < s.Size() {
smallest, toCheck = o, s
}
ix := NewSet(smallest.Size())
for nm := range smallest {
if toCheck.Contains(nm) {
ix.Add(nm)
}
}
return ix
}
func (s Set) Union(o Set) Set {
un := NewSet(s.Size() + o.Size())
for nm := range s {
un.Add(nm)
}
for nm := range o {
un.Add(nm)
}
return un
}
func (s Set) ToSortedSlice() []string {
sl := make([]string, 0, s.Size())
for nm := range s {
sl = append(sl, nm)
}
slices.Sort(sl)
return sl
}