work
This commit is contained in:
242
2024/go/day23/day23.go
Normal file
242
2024/go/day23/day23.go
Normal file
@@ -0,0 +1,242 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user