RosettaCodeData/Task/Modified-random-distribution/Go/modified-random-distributio...

66 lines
1.5 KiB
Go

package main
import (
"fmt"
"math"
"math/rand"
"strings"
"time"
)
func rng(modifier func(x float64) float64) float64 {
for {
r1 := rand.Float64()
r2 := rand.Float64()
if r2 < modifier(r1) {
return r1
}
}
}
func commatize(n int) string {
s := fmt.Sprintf("%d", n)
if n < 0 {
s = s[1:]
}
le := len(s)
for i := le - 3; i >= 1; i -= 3 {
s = s[0:i] + "," + s[i:]
}
if n >= 0 {
return s
}
return "-" + s
}
func main() {
rand.Seed(time.Now().UnixNano())
modifier := func(x float64) float64 {
if x < 0.5 {
return 2 * (0.5 - x)
}
return 2 * (x - 0.5)
}
const (
N = 100000
NUM_BINS = 20
HIST_CHAR = "■"
HIST_CHAR_SIZE = 125
)
bins := make([]int, NUM_BINS) // all zero by default
binSize := 1.0 / NUM_BINS
for i := 0; i < N; i++ {
rn := rng(modifier)
bn := int(math.Floor(rn / binSize))
bins[bn]++
}
fmt.Println("Modified random distribution with", commatize(N), "samples in range [0, 1):\n")
fmt.Println(" Range Number of samples within that range")
for i := 0; i < NUM_BINS; i++ {
hist := strings.Repeat(HIST_CHAR, int(math.Round(float64(bins[i])/HIST_CHAR_SIZE)))
fi := float64(i)
fmt.Printf("%4.2f ..< %4.2f %s %s\n", binSize*fi, binSize*(fi+1), hist, commatize(bins[i]))
}
}