2024 Day 23 Complete
This commit is contained in:
parent
4f5898255b
commit
268d0a0141
3380
2024/day23/input
Normal file
3380
2024/day23/input
Normal file
File diff suppressed because it is too large
Load Diff
179
2024/day23/main.go
Normal file
179
2024/day23/main.go
Normal 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
32
2024/day23/testinput
Normal 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
72
helpers/set.go
Normal 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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user