You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

191 lines
4.0 KiB
Go

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])
}