Repository: vaskoz/dailycodingproblem-go (go)

Issue:
Day 303
Good morning! Here's your coding interview problem for today.

This problem was asked by Microsoft.

Given a clock time in `hh:mm` format, determine, to the nearest degree, the angle between the hour and the minute hands.

Bonus: When, during the course of a day, will the angle be zero?

Pull request description:
Day303
Resolves #616.

Patch:
diff --git a/README.md b/README.md
index 49da401..9735534 100644
--- a/README.md
+++ b/README.md
@@ -309,3 +309,4 @@ problems from
 * [Day 299](https://github.com/vaskoz/dailycodingproblem-go/issues/611)
 * [Day 300](https://github.com/vaskoz/dailycodingproblem-go/issues/612)
 * [Day 302](https://github.com/vaskoz/dailycodingproblem-go/issues/615)
+* [Day 303](https://github.com/vaskoz/dailycodingproblem-go/issues/616)
diff --git a/day303/problem.go b/day303/problem.go
new file mode 100644
index 0000000..4b35ac6
--- /dev/null
+++ b/day303/problem.go
@@ -0,0 +1,35 @@
+package day303
+
+import "math"
+
+// AngleClockHands returns the nearest angle between clock hands.
+// Works at minute granularity.
+func AngleClockHands(hh, mm int) int {
+	if hh < 0 || hh >= 24 || mm < 0 || mm >= 60 {
+		panic("invalid time")
+	}
+	if hh >= 12 {
+		hh -= 12
+	}
+	hourAngle := 360.0 * float64(hh) / 12.0
+	minuteAngle := 360.0 * float64(mm) / 60.0
+	diffAngle := math.Abs(hourAngle - minuteAngle)
+	if diffAngle > 180 {
+		diffAngle -= 360
+	}
+	return int(math.Round(math.Abs(diffAngle)))
+}
+
+// TimesOverlappingHands returns all the [hh:mm] pairs with overlapping
+// clock hands by checking all possible 12*60 hour/minute possibilities.
+func TimesOverlappingHands() [][]int {
+	var result [][]int
+	for h := 0; h < 12; h++ {
+		for m := 0; m < 60; m++ {
+			if angle := AngleClockHands(h, m); angle == 0 {
+				result = append(result, []int{h, m})
+			}
+		}
+	}
+	return result
+}


Test patch:
diff --git a/day303/problem_test.go b/day303/problem_test.go
new file mode 100644
index 0000000..6f88ec1
--- /dev/null
+++ b/day303/problem_test.go
@@ -0,0 +1,59 @@
+package day303
+
+import (
+	"reflect"
+	"testing"
+)
+
+// nolint
+var testcases = []struct {
+	hh, mm int
+	angle  int
+}{
+	{12, 00, 0},
+	{11, 00, 30},
+}
+
+func TestAngleClockHands(t *testing.T) {
+	t.Parallel()
+	for _, tc := range testcases {
+		if angle := AngleClockHands(tc.hh, tc.mm); angle != tc.angle {
+			t.Errorf("Expected %v, got %v", tc.angle, angle)
+		}
+	}
+}
+
+func TestAngleClockHandsBadTime(t *testing.T) {
+	t.Parallel()
+	defer func() {
+		if err := recover(); err == nil {
+			t.Errorf("Expected a panic with an invalid time")
+		}
+	}()
+	AngleClockHands(20, 60)
+}
+
+func BenchmarkAngleClockHands(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			AngleClockHands(tc.hh, tc.mm)
+		}
+	}
+}
+
+func TestTimesOverlappingHands(t *testing.T) {
+	t.Parallel()
+	result := TimesOverlappingHands()
+	expected := [][]int{
+		{0, 0}, {1, 5}, {2, 10}, {3, 15}, {4, 20}, {5, 25}, {6, 30}, {7, 35}, {8, 40}, {9, 45}, {10, 50}, {11, 55},
+	}
+	if !reflect.DeepEqual(result, expected) {
+		t.Errorf("Expected %v, got %v", result, expected)
+	}
+}
+
+func BenchmarkTimesOverlappingHands(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		TimesOverlappingHands()
+	}
+}