Given a random number generator, (rng), generating numbers in the range 0.0 .. 1.0 called rgen, for example; and a function modifier(x)
taking an number in the same range and generating the probability that the input should be generated, in the same range 0..1; then implement the following algorithm for generating random numbers to the probability given by function modifier:

while True:
    random1 = rgen()
    random2 = rgen()
    if random2 < modifier(random1):
        answer = random1
        break
    endif
endwhile
Task

 Create a modifier function that generates a 'V' shaped probability of number generation using something like, for example:
                      modifier(x)  =  2*(0.5 - x)  if x < 0.5  else 2*(x - 0.5) 

 Create a generator of random numbers with probabilities modified by the above function.
 Generate >= 10,000 random numbers subject to the probability modification.
 Output a textual histogram with from 11 to 21 bins showing the distribution of the random numbers generated.


Show your output here, on this page.




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]))
    }
}