Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/python-wasm
Path: blob/main/python/pylang/src/lib/random.py
1398 views
1
###########################################################
2
# pylang Standard Library
3
# Author: Alexander Tsepkov
4
# Copyright 2013 Pyjeon Software LLC
5
# License: Apache License 2.0
6
# This library is covered under Apache license, so that
7
# you can distribute it with your pylang applications.
8
###########################################################
9
10
# basic implementation of Python's 'random' library
11
12
# JavaScript's Math.random() does not allow seeding its random generator.
13
# To bypass that, this module implements its own version that can be seeded.
14
# I decided on RC4 algorithm for this.
15
16
_seed_state = {'key': [], 'key_i': 0, 'key_j': 0}
17
18
19
def _get_random_byte():
20
_seed_state.key_i = (_seed_state.key_i + 1) % 256
21
_seed_state.key_j = (_seed_state.key_j +
22
_seed_state.key[_seed_state.key_i]) % 256
23
_seed_state.key[_seed_state.key_i], _seed_state.key[_seed_state.key_j] = \
24
_seed_state.key[_seed_state.key_j], _seed_state.key[_seed_state.key_i]
25
return _seed_state.key[(_seed_state.key[_seed_state.key_i] + \
26
_seed_state.key[_seed_state.key_j]) % 256]
27
28
29
def seed(x=Date().getTime()):
30
_seed_state.key_i = _seed_state.key_j = 0
31
if jstype(x) is 'number':
32
x = x.toString()
33
elif jstype(x) is not 'string':
34
raise TypeError("unhashable type: '" + jstype(x) + "'")
35
for i in range(256):
36
_seed_state.key[i] = i
37
j = 0
38
for i in range(256):
39
j = (j + _seed_state.key[i] + x.charCodeAt(i % x.length)) % 256
40
_seed_state.key[i], _seed_state.key[j] = _seed_state.key[
41
j], _seed_state.key[i]
42
43
44
seed()
45
46
47
def random():
48
n = 0
49
m = 1
50
for i in range(8):
51
n += _get_random_byte() * m
52
m *= 256
53
return n / 0x10000000000000000
54
55
56
# unlike the python version, this DOES build a range object, feel free to reimplement
57
def randrange():
58
return choice(range.apply(this, arguments))
59
60
61
def randint(a, b):
62
return int(random() * (b - a + 1) + a)
63
64
65
def uniform(a, b):
66
return random() * (b - a) + a
67
68
69
def choice(seq):
70
if len(seq) > 0:
71
return seq[Math.floor(random() * len(seq))]
72
else:
73
raise IndexError()
74
75
76
# uses Fisher-Yates algorithm to shuffle an array
77
def shuffle(x, random_f=random):
78
x = list(x)
79
for i in range(len(x)):
80
j = Math.floor(random_f() * (i + 1))
81
x[i], x[j] = x[j], x[i]
82
return x
83
84
85
# similar to shuffle, but only shuffles a subset and creates a copy
86
def sample(population, k):
87
x = list(population)[:]
88
for i in range(len(population) - 1, len(population) - k - 1, -1):
89
j = Math.floor(random() * (i + 1))
90
x[i], x[j] = x[j], x[i]
91
return x[-k:]
92
93