Path: blob/main/python/pylang/src/lib/random.py
1398 views
###########################################################1# pylang Standard Library2# Author: Alexander Tsepkov3# Copyright 2013 Pyjeon Software LLC4# License: Apache License 2.05# This library is covered under Apache license, so that6# you can distribute it with your pylang applications.7###########################################################89# basic implementation of Python's 'random' library1011# JavaScript's Math.random() does not allow seeding its random generator.12# To bypass that, this module implements its own version that can be seeded.13# I decided on RC4 algorithm for this.1415_seed_state = {'key': [], 'key_i': 0, 'key_j': 0}161718def _get_random_byte():19_seed_state.key_i = (_seed_state.key_i + 1) % 25620_seed_state.key_j = (_seed_state.key_j +21_seed_state.key[_seed_state.key_i]) % 25622_seed_state.key[_seed_state.key_i], _seed_state.key[_seed_state.key_j] = \23_seed_state.key[_seed_state.key_j], _seed_state.key[_seed_state.key_i]24return _seed_state.key[(_seed_state.key[_seed_state.key_i] + \25_seed_state.key[_seed_state.key_j]) % 256]262728def seed(x=Date().getTime()):29_seed_state.key_i = _seed_state.key_j = 030if jstype(x) is 'number':31x = x.toString()32elif jstype(x) is not 'string':33raise TypeError("unhashable type: '" + jstype(x) + "'")34for i in range(256):35_seed_state.key[i] = i36j = 037for i in range(256):38j = (j + _seed_state.key[i] + x.charCodeAt(i % x.length)) % 25639_seed_state.key[i], _seed_state.key[j] = _seed_state.key[40j], _seed_state.key[i]414243seed()444546def random():47n = 048m = 149for i in range(8):50n += _get_random_byte() * m51m *= 25652return n / 0x10000000000000000535455# unlike the python version, this DOES build a range object, feel free to reimplement56def randrange():57return choice(range.apply(this, arguments))585960def randint(a, b):61return int(random() * (b - a + 1) + a)626364def uniform(a, b):65return random() * (b - a) + a666768def choice(seq):69if len(seq) > 0:70return seq[Math.floor(random() * len(seq))]71else:72raise IndexError()737475# uses Fisher-Yates algorithm to shuffle an array76def shuffle(x, random_f=random):77x = list(x)78for i in range(len(x)):79j = Math.floor(random_f() * (i + 1))80x[i], x[j] = x[j], x[i]81return x828384# similar to shuffle, but only shuffles a subset and creates a copy85def sample(population, k):86x = list(population)[:]87for i in range(len(population) - 1, len(population) - k - 1, -1):88j = Math.floor(random() * (i + 1))89x[i], x[j] = x[j], x[i]90return x[-k:]919293