Repository: vaskoz/dailycodingproblem-go (go)

Issue:
Day 262
Good morning! Here's your coding interview problem for today.

This problem was asked by Mozilla.

A bridge in a connected (undirected) graph is an edge that, if removed, causes the graph to become disconnected. Find all the bridges in a graph.

Pull request:
Day262
Resolves #538.

Patch:
diff --git a/README.md b/README.md
index 80baf4d..8d434d5 100644
--- a/README.md
+++ b/README.md
@@ -273,6 +273,7 @@ problems from
 * [Day 259](https://github.com/vaskoz/dailycodingproblem-go/issues/531)
 * [Day 260](https://github.com/vaskoz/dailycodingproblem-go/issues/533)
 * [Day 261](https://github.com/vaskoz/dailycodingproblem-go/issues/534)
+* [Day 262](https://github.com/vaskoz/dailycodingproblem-go/issues/538)
 * [Day 263](https://github.com/vaskoz/dailycodingproblem-go/issues/539)
 * [Day 266](https://github.com/vaskoz/dailycodingproblem-go/issues/542)
 * [Day 267](https://github.com/vaskoz/dailycodingproblem-go/issues/543)
diff --git a/day262/problem.go b/day262/problem.go
new file mode 100644
index 0000000..ecdf4e8
--- /dev/null
+++ b/day262/problem.go
@@ -0,0 +1,68 @@
+package day262
+
+// Edge is an undirected edge from a Start node to an End node.
+type Edge struct {
+	Start, End int
+}
+
+// undirectedGraph is an undirected graph.
+// Edges will be inserted as 2-directed edges in opposite directions.
+type undirectedGraph map[int]map[int]struct{}
+
+// FindAllBridges returns all bridges in a given UndirectedGraph.
+func FindAllBridges(edges []Edge) []Edge {
+	graph := make(undirectedGraph)
+	for _, e := range edges {
+		if _, found := graph[e.Start]; !found {
+			graph[e.Start] = make(map[int]struct{})
+		}
+		if _, found := graph[e.End]; !found {
+			graph[e.End] = make(map[int]struct{})
+		}
+		graph[e.Start][e.End] = struct{}{}
+		graph[e.End][e.Start] = struct{}{}
+	}
+	visited := make([]bool, len(graph))
+	disc := make([]int, len(graph))
+	low := make([]int, len(graph))
+	parent := make([]int, len(graph))
+	for i := range disc {
+		disc[i] = int(^uint(0) >> 1)
+		low[i] = int(^uint(0) >> 1)
+		parent[i] = -1
+	}
+	var result []Edge
+	for i := range visited {
+		if !visited[i] {
+			result = findAllBridges(graph, i, 0, visited, parent, low, disc, result)
+		}
+	}
+	return result
+}
+
+func findAllBridges(graph undirectedGraph, u, time int, visited []bool, parent, low, disc []int, result []Edge) []Edge {
+	visited[u] = true
+	disc[u] = time
+	low[u] = time
+	time++
+	for v := range graph[u] {
+		if !visited[v] {
+			parent[v] = u
+			result = findAllBridges(graph, v, time, visited, parent, low, disc, result)
+			low[u] = min(low[u], low[v])
+			if low[v] > disc[u] {
+				result = append(result, Edge{u, v})
+			}
+		} else if v != parent[u] {
+			low[u] = min(low[u], disc[v])
+		}
+	}
+	return result
+}
+
+func min(a, b int) int {
+	if a < b {
+		return a
+	}
+	return b
+}


Test patch:
diff --git a/day262/problem_test.go b/day262/problem_test.go
new file mode 100644
index 0000000..50af10c
--- /dev/null
+++ b/day262/problem_test.go
@@ -0,0 +1,42 @@
+package day262
+
+import (
+	"reflect"
+	"testing"
+)
+
+// nolint
+var testcases = []struct {
+	graph   []Edge
+	bridges []Edge
+}{
+	{
+		[]Edge{{1, 0}, {0, 2}, {2, 1}, {0, 3}, {3, 4}},
+		[]Edge{{3, 4}, {0, 3}},
+	},
+	{
+		[]Edge{{0, 1}, {1, 2}, {2, 3}},
+		[]Edge{{2, 3}, {1, 2}, {0, 1}},
+	},
+	{
+		[]Edge{{0, 1}, {1, 2}, {2, 0}, {1, 3}, {1, 4}, {1, 6}, {3, 5}, {4, 5}},
+		[]Edge{{1, 6}},
+	},
+}
+
+func TestFindAllBridges(t *testing.T) {
+	t.Parallel()
+	for _, tc := range testcases {
+		if bridges := FindAllBridges(tc.graph); !reflect.DeepEqual(bridges, tc.bridges) {
+			t.Errorf("Expected %v, got %v", tc.bridges, bridges)
+		}
+	}
+}
+
+func BenchmarkFindAllBridges(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			FindAllBridges(tc.graph)
+		}
+	}
+}