From db90e85c8973ec2f25581c223c43ba26f751b5cb Mon Sep 17 00:00:00 2001 From: Vasko Zdravevski Date: Tue, 20 Nov 2018 20:17:31 -0700 Subject: [PATCH 1/2] day 90: randomly generate from missing integers --- day90/problem.go | 41 ++++++++++++++++++++++++++++++++++++ day90/problem_test.go | 49 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 day90/problem.go create mode 100644 day90/problem_test.go diff --git a/day90/problem.go b/day90/problem.go new file mode 100644 index 0000000..fb6f868 --- /dev/null +++ b/day90/problem.go @@ -0,0 +1,41 @@ +package day90 + +import ( + "math/rand" + "time" +) + +var random *rand.Rand + +// getRandom returns a *math.Rand. +func getRandom() *rand.Rand { + if random == nil { + random = rand.New(rand.NewSource(time.Now().UnixNano())) + } + return random +} + +// RandMissingNumbers randomly generates a number from 0 to n-1 that isn't in l. +// Runs in O(N) time and O(l) space. +func RandMissingNumbers(n int, l []int) int { + m := make(map[int]struct{}) + for _, v := range l { + m[v] = struct{}{} + } + size := n - len(m) + if size == 0 { + return -1 + } + pos := getRandom().Intn(size) + val := -1 + var i int + for i = 0; i < n; i++ { + if _, found := m[i]; !found { + val++ + } + if val == pos { + break + } + } + return i +} diff --git a/day90/problem_test.go b/day90/problem_test.go new file mode 100644 index 0000000..fa1b131 --- /dev/null +++ b/day90/problem_test.go @@ -0,0 +1,49 @@ +package day90 + +import "testing" + +var testcases = []struct { + n int + l []int + distribution float64 +}{ + {5, []int{0, 1, 2, 2}, 0.5}, + {5, []int{0, 1, 0, 1}, 0.333}, + {5, []int{0, 0, 0}, 0.25}, + {5, []int{0, 1, 2, 3}, 1.0}, +} + +func TestRandMissingNumbers(t *testing.T) { + //t.Parallel()//don't run in parallel + for _, tc := range testcases { + results := make(map[int]int) + const iterations = 1000 + for i := 0; i < iterations; i++ { + results[RandMissingNumbers(tc.n, tc.l)]++ + } + for _, v := range results { + delta := (float64(v) / float64(iterations)) - tc.distribution + if delta < 0 { + delta = -delta + } + if delta > 0.1 { + t.Errorf("Exceeded 0.1 tolerance for expected %v distribution", tc.distribution) + } + } + } +} + +func TestRandMissingNoNumbers(t *testing.T) { + //t.Parallel()//don't run in parallel + if result := RandMissingNumbers(5, []int{0, 1, 2, 3, 4}); result != -1 { + t.Errorf("Expected -1 for a list that includes all possible numbers") + } +} + +func BenchmarkRandMissingNumbers(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, tc := range testcases { + RandMissingNumbers(tc.n, tc.l) + } + } +} From 576b16ae90f514929d3c0096f91fbe505403a8ce Mon Sep 17 00:00:00 2001 From: Vasko Zdravevski Date: Tue, 20 Nov 2018 20:18:04 -0700 Subject: [PATCH 2/2] add day 90 to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 56aaefc..4b4cd17 100644 --- a/README.md +++ b/README.md @@ -99,3 +99,4 @@ problems from * [Day 87](https://github.com/vaskoz/dailycodingproblem-go/issues/183) * [Day 88](https://github.com/vaskoz/dailycodingproblem-go/issues/185) * [Day 89](https://github.com/vaskoz/dailycodingproblem-go/issues/187) +* [Day 90](https://github.com/vaskoz/dailycodingproblem-go/issues/189)