-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathutilities.py
60 lines (47 loc) · 1.57 KB
/
utilities.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import functools
import random
import time
def timing(func):
"""Function decorator which prints the time in milliseconds for which `func` ran"""
@functools.wraps(func)
def wrapper(*args):
start = time.monotonic()
return_value = func(*args)
end = time.monotonic()
print("Function '{}' took {:.2f} ms".format(func.__name__, (end - start) * 1000.0))
return return_value
return wrapper
def weighted_choice(sequence, weights):
"""Return a random element from `sequence`, where each element in `sequence` is weighted by the corresponding
element in `weights`.
`Sequence` must be non-empty. `Weights` must be the same length as `sequence`.
>>> weighted_choice([1, 2], [1, 0])
1
>>> weighted_choice([1, 2], [0, 0])
2
"""
if len(sequence) <= 0:
raise ValueError('Sequence must be non-empty')
if len(sequence) != len(weights):
raise ValueError('Sequence and weights must have same length')
total = sum(weights)
r = random.uniform(0, total)
# Documentation for random.uniform says: r may or may not be total, depending on floating-point rounding
if r == total:
return sequence[-1]
index = 0
while r >= 0:
r -= weights[index]
index += 1
return sequence[index - 1]
def clamp(n, smallest, largest):
"""The value of `n` clamped to the range [`smallest`, `largest`]
>>> clamp(1, 4, 10)
4
>>> clamp(12, 4, 10)
10
"""
return max(smallest, min(n, largest))
if __name__ == '__main__':
import doctest
doctest.testmod()