Repository: vaskoz/dailycodingproblem-go (go)

Issue:
Day 280
Good morning! Here's your coding interview problem for today.

This problem was asked by Pandora.

Given an undirected graph, determine if it contains a cycle.

Pull request description:
Day280
Resolves #568.

Patch:
diff --git a/README.md b/README.md
index fa1c197..db05312 100644
--- a/README.md
+++ b/README.md
@@ -283,3 +283,4 @@ problems from
 * [Day 273](https://github.com/vaskoz/dailycodingproblem-go/issues/556)
 * [Day 277](https://github.com/vaskoz/dailycodingproblem-go/issues/563)
 * [Day 279](https://github.com/vaskoz/dailycodingproblem-go/issues/566)
+* [Day 280](https://github.com/vaskoz/dailycodingproblem-go/issues/568)
diff --git a/day280/problem.go b/day280/problem.go
new file mode 100644
index 0000000..6cb5540
--- /dev/null
+++ b/day280/problem.go
@@ -0,0 +1,25 @@
+package day280
+
+// UndirectedGraph is a connected undirected adjacency list.
+type UndirectedGraph map[int]map[int]struct{}
+
+// HasCycle answers if the connected undirected graph is cyclic.
+func HasCycle(g UndirectedGraph) bool {
+	var start int
+	for node := range g {
+		start = node
+		break
+	}
+	visits := make(map[int]bool)
+	return hasCycle(g, start, visits)
+}
+
+func hasCycle(g UndirectedGraph, start int, visits map[int]bool) bool {
+	visits[start] = true
+	for node := range g[start] {
+		if visited := visits[node]; visited || hasCycle(g, node, visits) {
+			return true
+		}
+	}
+	return false
+}


Test patch:
diff --git a/day280/problem_test.go b/day280/problem_test.go
new file mode 100644
index 0000000..a6feab0
--- /dev/null
+++ b/day280/problem_test.go
@@ -0,0 +1,45 @@
+package day280
+
+import "testing"
+
+// nolint
+var testcases = []struct {
+	g      UndirectedGraph
+	cyclic bool
+}{
+	{
+		UndirectedGraph{
+			0: {2: struct{}{}, 3: struct{}{}},
+			1: {0: struct{}{}},
+			2: {0: struct{}{}},
+			3: {4: struct{}{}},
+		},
+		true,
+	},
+	{
+		UndirectedGraph{
+			0: {1: struct{}{}},
+			1: {2: struct{}{}},
+			2: {3: struct{}{}},
+			3: {4: struct{}{}},
+		},
+		false,
+	},
+}
+
+func TestHasCycle(t *testing.T) {
+	t.Parallel()
+	for _, tc := range testcases {
+		if cyclic := HasCycle(tc.g); cyclic != tc.cyclic {
+			t.Errorf("Expected %v, got %v", tc.cyclic, cyclic)
+		}
+	}
+}
+
+func BenchmarkHasCycle(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			HasCycle(tc.g)
+		}
+	}
+}