package day25 import ( "fmt" "strings" "gitea.paas.celticinfo.fr/oabrivard/aoc2023/utils" ) type Graph map[string]map[string]bool type Edge struct { left string right string } func buildGraph(lines []string) Graph { graph := map[string]map[string]bool{} for _, line := range lines { parts := strings.Split(line, ":") src := parts[0] if _, found := graph[src]; !found { graph[src] = map[string]bool{} } links := graph[src] dests := strings.Fields(strings.TrimSpace(parts[1])) for _, dst := range dests { links[dst] = true if _, found := graph[dst]; !found { graph[dst] = map[string]bool{} } reverseLink := graph[dst] reverseLink[src] = true } } return graph } func printGraph(graph Graph) { for k1, v1 := range graph { fmt.Print(k1, ": ") for k2 := range v1 { fmt.Print(k2, " ") } fmt.Println("") } } func countComponents(graph Graph) int { visited := map[string]bool{} count := 0 for node := range graph { if !visited[node] { count++ queue := utils.NewQueue[string]() queue.Enqueue(node) for queue.HasElement() { curNode := queue.Dequeue() visited[curNode] = true for linkedNode := range graph[curNode] { if !visited[linkedNode] { queue.Enqueue(linkedNode) } } } } } return count } func buildVerticesLists(graph Graph) []map[string]bool { visited := map[string]bool{} result := []map[string]bool{} currSubgraph := 0 for node := range graph { if !visited[node] { result = append(result, map[string]bool{}) result[currSubgraph][node] = true queue := utils.NewQueue[string]() queue.Enqueue(node) for queue.HasElement() { curNode := queue.Dequeue() visited[curNode] = true result[currSubgraph][curNode] = true for linkedNode := range graph[curNode] { if !visited[linkedNode] { queue.Enqueue(linkedNode) } } } currSubgraph++ } } return result } func buildEdgeList(graph Graph) []Edge { edges := map[Edge]bool{} for node, connectedNodes := range graph { for connectedNode := range connectedNodes { _, found1 := edges[Edge{node, connectedNode}] _, found2 := edges[Edge{connectedNode, node}] if !found1 && !found2 { edges[Edge{node, connectedNode}] = true } } } result := []Edge{} for e := range edges { result = append(result, e) } return result } func findEdgesToDelete(graph Graph, edges []Edge) (bool, *Edge, *Edge, *Edge) { for i := 0; i < len(edges); i++ { for j := i + 1; j < len(edges); j++ { for k := j + 1; k < len(edges); k++ { // Delete edges i, j and k from graph delete(graph[edges[i].left], edges[i].right) delete(graph[edges[i].right], edges[i].left) delete(graph[edges[j].left], edges[j].right) delete(graph[edges[j].right], edges[j].left) delete(graph[edges[k].left], edges[k].right) delete(graph[edges[k].right], edges[k].left) // count components count := countComponents(graph) // restore Graph graph[edges[i].left][edges[i].right] = true graph[edges[i].right][edges[i].left] = true graph[edges[j].left][edges[j].right] = true graph[edges[j].right][edges[j].left] = true graph[edges[k].left][edges[k].right] = true graph[edges[k].right][edges[k].left] = true if count == 2 { return true, &edges[i], &edges[j], &edges[k] } } } } return false, nil, nil, nil } func Part1(lines []string) int { graph := buildGraph(lines) printGraph(graph) edges := buildEdgeList(graph) fmt.Println(edges) success, edge1, edge2, edge3 := findEdgesToDelete(graph, edges) if !success { return 0 } fmt.Println(*edge1) fmt.Println(*edge2) fmt.Println(*edge3) delete(graph[edge1.left], edge1.right) delete(graph[edge1.right], edge1.left) delete(graph[edge2.left], edge2.right) delete(graph[edge2.right], edge2.left) delete(graph[edge3.left], edge3.right) delete(graph[edge3.right], edge3.left) result := buildVerticesLists(graph) fmt.Println(result[0]) fmt.Println(result[1]) return len(result[0]) * len(result[1]) }