Skip to content

Commit

Permalink
Merge pull request #190 from vaskoz/day90
Browse files Browse the repository at this point in the history
Day90
  • Loading branch information
vaskoz committed Nov 21, 2018
2 parents 7f3e25c + 576b16a commit d5fcdce
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
41 changes: 41 additions & 0 deletions day90/problem.go
Original file line number Diff line number Diff line change
@@ -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
}
49 changes: 49 additions & 0 deletions day90/problem_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
}

0 comments on commit d5fcdce

Please sign in to comment.