Modified random distribution: Difference between revisions

From Rosetta Code
Content added Content deleted
m (emphasis)
mNo edit summary
Line 23: Line 23:


Show your output here, on this page.
Show your output here, on this page.

=={{header|Julia}}==
<lang>using UnicodePlots

modifier(x) = (y = 2x - 1; y < 0 ? -y : y)
modrands(rands1, rands2) = [x for (i, x) in enumerate(rands1) if rands2[i] < modifier(x)]
histogram(modrands(rand(10000), rand(10000)), nbins = 15, closed = :left)
</lang>{{out}}
<pre>
┌ ┐
[0.0, 0.1) ┤▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 941
[0.1, 0.2) ┤▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 663
[0.2, 0.3) ┤▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 476
[0.3, 0.4) ┤▇▇▇▇▇▇▇▇▇▇▇ 288
[0.4, 0.5) ┤▇▇▇▇ 109
[0.5, 0.6) ┤▇▇▇▇ 118
[0.6, 0.7) ┤▇▇▇▇▇▇▇▇▇▇▇▇ 330
[0.7, 0.8) ┤▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 486
[0.8, 0.9) ┤▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 738
[0.9, 1.0) ┤▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 929
└ ┘
</pre>


=={{header|Python}}==
=={{header|Python}}==

Revision as of 03:54, 26 February 2021

Modified random distribution is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

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.

Julia

<lang>using UnicodePlots

modifier(x) = (y = 2x - 1; y < 0 ? -y : y) modrands(rands1, rands2) = [x for (i, x) in enumerate(rands1) if rands2[i] < modifier(x)] histogram(modrands(rand(10000), rand(10000)), nbins = 15, closed = :left)

</lang>

Output:
              ┌                                        ┐ 
   [0.0, 0.1) ┤▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 941   
   [0.1, 0.2) ┤▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 663             
   [0.2, 0.3) ┤▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 476                   
   [0.3, 0.4) ┤▇▇▇▇▇▇▇▇▇▇▇ 288                          
   [0.4, 0.5) ┤▇▇▇▇ 109                                 
   [0.5, 0.6) ┤▇▇▇▇ 118                                 
   [0.6, 0.7) ┤▇▇▇▇▇▇▇▇▇▇▇▇ 330                         
   [0.7, 0.8) ┤▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 486                    
   [0.8, 0.9) ┤▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 738          
   [0.9, 1.0) ┤▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 929  
              └                                        ┘

Python

<lang python>import random from typing import List, Callable, Optional


def modifier(x: float) -> float:

   """
   V-shaped, modifier(x) goes from 1 at 0 to 0 at 0.5 then back to 1 at 1.0 .
   Parameters
   ----------
   x : float
       Number, 0.0 .. 1.0 .
   Returns
   -------
   float
       Target probability for generating x; between 0 and 1.
   """
   return 2*(.5 - x) if x < 0.5 else 2*(x - .5)


def modified_random_distribution(modifier: Callable[[float], float],

                                n: int) -> List[float]:
   """
   Generate n random numbers between 0 and 1 subject to modifier.
   Parameters
   ----------
   modifier : Callable[[float], float]
       Target random number gen. 0 <= modifier(x) < 1.0 for 0 <= x < 1.0 .
   n : int
       number of random numbers generated.
   Returns
   -------
   List[float]
       n random numbers generated with given probability.
   """
   d: List[float] = []
   while len(d) < n:
       r1 = prob = random.random()
       if random.random() < modifier(prob):
           d.append(r1)
   return d


if __name__ == '__main__':

   from collections import Counter
   data = modified_random_distribution(modifier, 50_000)
   bins = 15
   counts = Counter(d // (1 / bins) for d in data)
   #
   mx = max(counts.values())
   print("   BIN, COUNTS, DELTA: HISTOGRAM\n")
   last: Optional[float] = None
   for b, count in sorted(counts.items()):
       delta = 'N/A' if last is None else str(count - last)
       print(f"  {b / bins:5.2f},  {count:4},  {delta:>4}: "
             f"{'#' * int(40 * count / mx)}")
       last = count</lang>
Output:
   BIN, COUNTS, DELTA: HISTOGRAM

   0.00,  6326,   N/A: ########################################
   0.07,  5327,  -999: #################################
   0.13,  4487,  -840: ############################
   0.20,  3495,  -992: ######################
   0.27,  2601,  -894: ################
   0.33,  1744,  -857: ###########
   0.40,   914,  -830: #####
   0.47,   225,  -689: #
   0.53,   899,   674: #####
   0.60,  1783,   884: ###########
   0.67,  2623,   840: ################
   0.73,  3566,   943: ######################
   0.80,  4383,   817: ###########################
   0.87,  5422,  1039: ##################################
   0.93,  6205,   783: #######################################