Zaimplementuj generator liczb pseudolosowych korzystając z algorytmu Wichmann–Hill. Zmodyfikuj generator tak, aby zwracał liczby: z zakresu z częstosliwością:

  • 1-10 -> 25%
  • 11-50 -> 15%
  • 51-75 -> 35%
  • 76 - 99 -> 20%
  • 100 -> 5%

Na próbce 100 tysięcy liczb, oblicz rozkład.

function(s1, s2, s3)

s1 = mod ( 171 * s1, 30269 )

s2 = mod ( 172 * s2, 30307 )

s3 = mod ( 170 * s3, 30323 )

r = mod ( s1/30269 + s2/30307 + s3/30323, 1 )

return r


In [ ]:
import time
from functools import partial
from collections import Counter

class RandomNumbersGenerator():
    def __init__(self):
        self.s1 = time.time()
        self.s2 = time.time()
        self.s3 = time.time()
        
    def _linear_rng(self):
        while True:
            self.s1 = (171 * self.s1) % 30269
            self.s2 = (172 * self.s2) % 30307
            self.s3 = (170 * self.s3) % 30323
            yield (self.s1 / 30269.0 + self.s2 / 30307.0 + self.s3 / 30323.0) % 1.0
            
    def __iter__(self):
        rng = self._linear_rng()
        inrange = lambda min, max: int(next(rng) * abs(max - min) + min)
        while True:
            rn = next(rng)
            if rn <= 0.25:
                 yield inrange(1, 10)
            elif 0.25 < rn <= 0.4:
                yield inrange(11, 50)
            elif 0.4 < rn <= 0.75:
                yield inrange(51, 75)
            elif 0.75 < rn <= 0.95:
                yield inrange(76, 99)
            else:
                yield 100
                
    def __enter__(self):
        return iter(self)
    
    def __exit__(self, *args):
        pass

In [ ]:
AMOUNT = 100000
with RandomNumbersGenerator() as rng:
    rng_gen = partial(next, rng)
    ct = Counter()
    for i in range(AMOUNT):
        rn = rng_gen()
        if rn in range(1, 11):
            ct[(1, 10)] += 1
        elif rn in range(11, 51):
            ct[(11, 50)] += 1
        elif rn in range(51, 76):
            ct[(51, 75)] += 1
        elif rn in range(76, 100):
            ct[(76, 99)] += 1
        else:
            ct[(100,)] += 1
    print(sorted(ct.items(), key=lambda x: x[0]))