package day23 import ( "fmt" "regexp" "sort" "strings" ) type Lan struct { nodes []*Node } type Node struct { key string adjacent []*Node loops [][]*Node } func Part1(input string) int { total := 0 lan := &Lan{} pattern := `^([a-z]{2})-([a-z]{2})$` re := regexp.MustCompile(pattern) lines := strings.Split(input, "\n") for _, line := range lines { matches := re.FindAllStringSubmatch(line, -1) for _, match := range matches { lan.AddNode(match[1]) lan.AddNode(match[2]) lan.AddConnection(match[1], match[2]) lan.AddConnection(match[2], match[1]) } } for _, node := range lan.nodes { if node.key[0] == 't' { connections := node.adjacent for _, connection := range connections { c := lan.getNode(connection.key) for _, n1 := range c.adjacent { for _, n2 := range connections { if n1.key == n2.key { already_found := false for _, loop := range node.loops { if contains(loop, c.key) && contains(loop, n2.key) { already_found = true break } } for _, loop := range c.loops { if contains(loop, node.key) && contains(loop, n2.key) { already_found = true break } } for _, loop := range n2.loops { if contains(loop, c.key) && contains(loop, node.key) { already_found = true break } } if !already_found { already_found = true total++ loop := make([]*Node, 0) loop = append(loop, node) loop = append(loop, c) loop = append(loop, n2) node.loops = append(node.loops, loop) fmt.Printf("%v,%v,%v\n", node.key, c.key, n2.key) } } } } } } } lan.Print() t := 0 for _, node := range lan.nodes { if node.key[0] == 't' { t += len(node.loops) fmt.Printf("Node: %v\n", node.key) for _, loop := range node.loops { for _, n := range loop { fmt.Printf(" %v ", n.key) } fmt.Println() } } } fmt.Printf("Total: %d\n", t) return total } func Part2(input string) int { total := 0 lan := &Lan{} pattern := `^([a-z]{2})-([a-z]{2})$` re := regexp.MustCompile(pattern) lines := strings.Split(input, "\n") for _, line := range lines { matches := re.FindAllStringSubmatch(line, -1) for _, match := range matches { lan.AddNode(match[1]) lan.AddNode(match[2]) lan.AddConnection(match[1], match[2]) lan.AddConnection(match[2], match[1]) } } for _, node := range lan.nodes { connections := node.adjacent for _, connection := range connections { c := lan.getNode(connection.key) for _, n1 := range c.adjacent { for _, n2 := range connections { if n1.key == n2.key { already_found := false for _, loop := range node.loops { if contains(loop, c.key) && contains(loop, n2.key) { already_found = true break } } for _, loop := range c.loops { if contains(loop, node.key) && contains(loop, n2.key) { already_found = true break } } for _, loop := range n2.loops { if contains(loop, c.key) && contains(loop, node.key) { already_found = true break } } if !already_found { already_found = true total++ loop := make([]*Node, 0) loop = append(loop, node) loop = append(loop, c) loop = append(loop, n2) node.loops = append(node.loops, loop) fmt.Printf("%v,%v,%v\n", node.key, c.key, n2.key) } } } } } } lan.Print() maxLoop := 0 var maxNode *Node for _, node := range lan.nodes { if len(node.loops) > maxLoop { maxLoop = len(node.loops) maxNode = node } } fmt.Printf("Max: %d\n", len(maxNode.loops)) nodeList := make([]*Node, 0) keyList := make([]string, 0) for _, loop := range maxNode.loops { for _, l := range loop { if !contains(nodeList, l.key) { nodeList = append(nodeList, l) keyList = append(keyList, l.key) } } } sort.Strings(keyList) fmt.Println(strings.Join(keyList, ",")) return len(nodeList) } func (g *Lan) AddNode(key string) { if !contains(g.nodes, key) { g.nodes = append(g.nodes, &Node{key: key}) } } func (g *Lan) AddConnection(from, to string) { fromNode := g.getNode(from) toNode := g.getNode(to) if fromNode == nil || toNode == nil { err := fmt.Errorf("Error: Invalid edge (%v --> %v)", from, to) fmt.Println(err.Error()) } else if contains(fromNode.adjacent, to) { err := fmt.Errorf("Error: Existing edge (%v --> %v)", from, to) fmt.Println(err.Error()) } else { fromNode.adjacent = append(fromNode.adjacent, toNode) } } func (g *Lan) getNode(key string) *Node { for i, v := range g.nodes { if v.key == key { return g.nodes[i] } } return nil } func (g *Lan) Print() { for _, v := range g.nodes { fmt.Printf("\nNode %v : ", v.key) for _, v := range v.adjacent { fmt.Printf(" %v ", v.key) } fmt.Println() for _, loop := range v.loops { for _, v := range loop { if v != nil { fmt.Printf(" %v ", v.key) } } fmt.Println() } } } func contains(list []*Node, key string) bool { for _, v := range list { if key == v.key { return true } } return false }