Repository: vaskoz/dailycodingproblem-go (go)

Issue:
Day 283
Good morning! Here's your coding interview problem for today.

This problem was asked by Google.

A regular number in mathematics is defined as one which evenly divides some power of 60. Equivalently, we can say that a regular number is one whose only prime divisors are 2, 3, and 5.

These numbers have had many applications, from helping ancient Babylonians keep time to tuning instruments according to the diatonic scale.

Given an integer `N`, write a program that returns, in order, the first `N` regular numbers.

Pull request:
Day283
Resolves #577.

Patch:
diff --git a/README.md b/README.md
index b8df42c..e689b52 100644
--- a/README.md
+++ b/README.md
@@ -289,3 +289,4 @@ problems from
 * [Day 280](https://github.com/vaskoz/dailycodingproblem-go/issues/568)
 * [Day 281](https://github.com/vaskoz/dailycodingproblem-go/issues/572)
 * [Day 282](https://github.com/vaskoz/dailycodingproblem-go/issues/575)
+* [Day 283](https://github.com/vaskoz/dailycodingproblem-go/issues/577)
diff --git a/day283/problem.go b/day283/problem.go
new file mode 100644
index 0000000..8fede56
--- /dev/null
+++ b/day283/problem.go
@@ -0,0 +1,68 @@
+package day283
+
+// RegularNumbersFaster returns n regular numbers
+// using brute force.
+func RegularNumbersFaster(n int) []int {
+	if n < 0 {
+		panic("negative values are not possible")
+	} else if n == 0 {
+		return []int{}
+	}
+	result := make([]int, n)
+	result[0] = 1
+	var i2, i3, i5 int
+	next2, next3, next5 := 2, 3, 5
+	for i := 1; i < n; i++ {
+		result[i] = min(next2, next3, next5)
+		if result[i] == next2 {
+			i2++
+			next2 = result[i2] * 2
+		}
+		if result[i] == next3 {
+			i3++
+			next3 = result[i3] * 3
+		}
+		if result[i] == next5 {
+			i5++
+			next5 = result[i5] * 5
+		}
+	}
+	return result
+}
+
+func min(vals ...int) int {
+	smallest := vals[0]
+	for _, v := range vals {
+		if v < smallest {
+			smallest = v
+		}
+	}
+	return smallest
+}
+
+// RegularNumbersBrute returns n regular numbers
+// using brute force.
+func RegularNumbersBrute(n int) []int {
+	if n < 0 {
+		panic("negative values are not possible")
+	}
+	result := make([]int, 0, n)
+	count := 0
+	for x := 1; count < n; x++ {
+		remain := repeatDivide(x, 2)
+		remain = repeatDivide(remain, 3)
+		remain = repeatDivide(remain, 5)
+		if remain == 1 {
+			result = append(result, x)
+			count++
+		}
+	}
+	return result
+}
+
+func repeatDivide(val, factor int) int {
+	for val%factor == 0 {
+		val /= factor
+	}
+	return val
+}


Test patch:
diff --git a/day283/problem_test.go b/day283/problem_test.go
new file mode 100644
index 0000000..2ec7ede
--- /dev/null
+++ b/day283/problem_test.go
@@ -0,0 +1,70 @@
+package day283
+
+import (
+	"reflect"
+	"testing"
+)
+
+// nolint
+var testcases = []struct {
+	n        int
+	expected []int
+}{
+	{0, []int{}},
+	{1, []int{1}},
+	{2, []int{1, 2}},
+	{11, []int{1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15}},
+	{26, []int{1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60}},
+}
+
+func TestRegularNumbersFaster(t *testing.T) {
+	t.Parallel()
+	for _, tc := range testcases {
+		if result := RegularNumbersFaster(tc.n); !reflect.DeepEqual(result, tc.expected) {
+			t.Errorf("Expected %v, got %v", tc.expected, result)
+		}
+	}
+}
+
+func TestRegularNumbersFasterBadInput(t *testing.T) {
+	defer func() {
+		if err := recover(); err == nil {
+			t.Errorf("Expected a panic for a negative input")
+		}
+	}()
+	RegularNumbersFaster(-2)
+}
+
+func BenchmarkRegularNumbersFaster(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			RegularNumbersFaster(tc.n)
+		}
+	}
+}
+
+func TestRegularNumbersBrute(t *testing.T) {
+	t.Parallel()
+	for _, tc := range testcases {
+		if result := RegularNumbersBrute(tc.n); !reflect.DeepEqual(result, tc.expected) {
+			t.Errorf("Expected %v, got %v", tc.expected, result)
+		}
+	}
+}
+
+func TestRegularNumbersBruteBadInput(t *testing.T) {
+	defer func() {
+		if err := recover(); err == nil {
+			t.Errorf("Expected a panic for a negative input")
+		}
+	}()
+	RegularNumbersBrute(-2)
+}
+
+func BenchmarkRegularNumbersBrute(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, tc := range testcases {
+			RegularNumbersBrute(tc.n)
+		}
+	}
+}