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