Fix random distribution in bitArray.PickRandom (#2534)

* Fix random distribution in bitArray.PickRandom

Previously it was very biased. 63 "_" followed by a single "x" had
much greater odds of being chosen. Additionally, the last element was
skewed. This fixes that by first preproccessing the set of all true
indices, and then randomly selecting a single element from there.

This commit also makes the code here significantly simpler, and
improves test cases.

* unlock mtx right after we select true indices
This commit is contained in:
Dev Ojha
2018-10-05 00:00:50 -07:00
committed by Anton Kaliaev
parent 5b120d788a
commit c648c93807
3 changed files with 60 additions and 42 deletions

View File

@ -107,16 +107,29 @@ func TestSub(t *testing.T) {
}
func TestPickRandom(t *testing.T) {
for idx := 0; idx < 123; idx++ {
bA1 := NewBitArray(123)
bA1.SetIndex(idx, true)
index, ok := bA1.PickRandom()
if !ok {
t.Fatal("Expected to pick element but got none")
}
if index != idx {
t.Fatalf("Expected to pick element at %v but got wrong index", idx)
}
empty16Bits := "________________"
empty64Bits := empty16Bits + empty16Bits + empty16Bits + empty16Bits
testCases := []struct {
bA string
ok bool
}{
{`null`, false},
{`"x"`, true},
{`"` + empty16Bits + `"`, false},
{`"x` + empty16Bits + `"`, true},
{`"` + empty16Bits + `x"`, true},
{`"x` + empty16Bits + `x"`, true},
{`"` + empty64Bits + `"`, false},
{`"x` + empty64Bits + `"`, true},
{`"` + empty64Bits + `x"`, true},
{`"x` + empty64Bits + `x"`, true},
}
for _, tc := range testCases {
var bitArr *BitArray
err := json.Unmarshal([]byte(tc.bA), &bitArr)
require.NoError(t, err)
_, ok := bitArr.PickRandom()
require.Equal(t, tc.ok, ok, "PickRandom got an unexpected result on input %s", tc.bA)
}
}