-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
84 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package day66 | ||
|
||
import ( | ||
"math/rand" | ||
"time" | ||
) | ||
|
||
// BiasedCoin represents a biased coin. Not 50-50. | ||
type BiasedCoin struct { | ||
zeroBias int | ||
r *rand.Rand | ||
} | ||
|
||
// Toss throws the coin and returns 0 or 1 | ||
func (bc *BiasedCoin) Toss() int { | ||
if val := bc.r.Intn(100); val < bc.zeroBias { | ||
return 0 | ||
} | ||
return 1 | ||
} | ||
|
||
// NewBiasedCoin returns a biased coin for flipping. | ||
// zeroBias represents the amount of bias towards a zero value. | ||
// The higher the value of zeroBias the more you will see zeros. | ||
// a zeroBias of 50 will be a fair coin. | ||
func NewBiasedCoin(zeroBias int) *BiasedCoin { | ||
return &BiasedCoin{zeroBias: zeroBias, r: rand.New(rand.NewSource(time.Now().UnixNano()))} | ||
} | ||
|
||
// FairTosser represents a fair 50-50 coin tosser even if given an unfair coin. | ||
type FairTosser struct { | ||
bc *BiasedCoin | ||
} | ||
|
||
// Toss throws the coin and returns 0 or 1 and should be a 50-50 chance. | ||
func (ft *FairTosser) Toss() int { | ||
firstToss := ft.bc.Toss() | ||
secondToss := ft.bc.Toss() | ||
for firstToss == secondToss { | ||
firstToss = ft.bc.Toss() | ||
secondToss = ft.bc.Toss() | ||
} | ||
return firstToss | ||
} | ||
|
||
// NewFairTosser makes a biased coin fair. | ||
func NewFairTosser(bc *BiasedCoin) *FairTosser { | ||
return &FairTosser{bc: bc} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package day66 | ||
|
||
import "testing" | ||
|
||
func TestFairTosser(t *testing.T) { | ||
t.Parallel() | ||
bc := NewBiasedCoin(99) | ||
biasedResults := make([]int, 2) | ||
for i := 0; i < 100000; i++ { | ||
biasedResults[bc.Toss()]++ | ||
} | ||
if biasedResults[1] == 0 { | ||
t.Errorf("Should have received 1 at least once") | ||
} | ||
if ratio := biasedResults[0] / biasedResults[1]; ratio < 90 { | ||
t.Errorf("Expected the ratio of 0's to 1's to be near 99, but got %v", ratio) | ||
} | ||
ft := NewFairTosser(bc) | ||
fairResults := make([]int, 2) | ||
for i := 0; i < 100000; i++ { | ||
fairResults[ft.Toss()]++ | ||
} | ||
if ratio := float64(fairResults[0]) / float64(fairResults[1]); ratio < 0.9 || ratio > 1.1 { | ||
t.Errorf("Expected the ratio of 0's to 1's to be near 1.0, but got %v", ratio) | ||
} | ||
} | ||
|
||
func BenchmarkFairTosser(b *testing.B) { | ||
bc := NewBiasedCoin(99) | ||
ft := NewFairTosser(bc) | ||
for i := 0; i < b.N; i++ { | ||
ft.Toss() | ||
} | ||
} |