/
random.gleam
161 lines (156 loc) · 4.86 KB
/
random.gleam
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.15.6/dist/katex.min.css" integrity="sha384-ZPe7yZ91iWxYumsBEOn7ieg8q/o+qh/hQpSaPow8T6BwALcXSCS6C6fSRPIAnTQs" crossorigin="anonymous">
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.15.6/dist/katex.min.js" integrity="sha384-ljao5I1l+8KYFXG7LNEA7DyaFvuvSCmedUf6Y6JI7LJqiu8q5dEivP2nDdFH31V4" crossorigin="anonymous"></script>
////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.15.6/dist/contrib/auto-render.min.js" integrity="sha384-+XBljXPPiv+OzfbB3cVmLHf4hdUFHlWNZN5spNQ7rmHTXpd7WvJum6fIACpNNfIR" crossorigin="anonymous"></script>
////<script>
//// document.addEventListener("DOMContentLoaded", function() {
//// renderMathInElement(document.body, {
//// // customised options
//// // • auto-render specific keys, e.g.:
//// delimiters: [
//// {left: '$$', right: '$$', display: false},
//// // {left: '$', right: '$', display: false},
//// // {left: '\\(', right: '\\)', display: false},
//// {left: '\\[', right: '\\]', display: true}
//// ],
//// // • rendering keys, e.g.:
//// throwOnError : false
//// });
//// });
////</script>
////<style>
//// .katex { font-size: 1.1em; }
////</style>
////
//// A module containing functions for generating and randomizing data.
////
//// ---
////
//// * **Lists**
//// * [`shuffle`](#shuffle)
//// * **Data**
//// * [`bools`](#bools)
import gleam/list
import gleam/iterator
import gleam/pair
import gleam_stats/distributions/bernoulli
import gleam_stats/distributions/uniform
/// <div style="text-align: right;">
/// <a href="https://github.com/nicklasxyz/gleam_stats/issues">
/// <small>Spot a typo? Open an issue!</small>
/// </a>
/// </div>
///
/// Given a list as input shuffle and return it (along with the generator
/// that was also passed as input).
///
/// <details>
/// <summary>Example:</summary>
///
/// import gleam_stats/generators
/// import gleam_stats/random
///
/// pub fn example() {
/// let stream = generators.seed_pcg32(5, 1)
/// let shuffled_list =
/// random.shuffle([1, 10, 100], stream)
/// |> pair.first()
/// }
/// </details>
///
/// <div style="text-align: right;">
/// <a href="#">
/// <small>Back to top ↑</small>
/// </a>
/// </div>
///
pub fn shuffle(
list: List(a),
stream: iterator.Iterator(Int),
) -> #(List(a), iterator.Iterator(Int)) {
let length = list.length(list)
assert Ok(out) = bernoulli.bernoulli_random(stream, 0.5, length)
let shuffled_list = do_shuffle(list, length, pair.first(out))
#(shuffled_list, pair.second(out))
}
fn shuffle_list(a: List(a), b: List(a), c: List(Int)) -> List(a) {
case a, b, c {
[], _, _ -> b
_, [], _ -> a
[ax, ..ar], [bx, ..br], [cx, ..cr] ->
case cx {
1 -> [ax, ..shuffle_list(ar, b, cr)]
0 -> [bx, ..shuffle_list(a, br, cr)]
}
}
}
fn do_shuffle(list: List(a), list_length: Int, c: List(Int)) -> List(a) {
case list_length < 2 {
True -> list
False -> {
let split_length = list_length / 2
let a_list = list.take(list, split_length)
let b_list = list.drop(list, split_length)
let c1_list = list.take(c, split_length)
let c2_list = list.drop(c, split_length)
shuffle_list(
do_shuffle(a_list, split_length, c1_list),
do_shuffle(b_list, list_length - split_length, c2_list),
c,
)
}
}
}
/// <div style="text-align: right;">
/// <a href="https://github.com/nicklasxyz/gleam_stats/issues">
/// <small>Spot a typo? Open an issue!</small>
/// </a>
/// </div>
///
/// Generate a list of random boolean values where each outcome (True/False)
/// appears with 50% probability.
///
/// <details>
/// <summary>Example:</summary>
///
/// import gleam_stats/generators
/// import gleam_stats/random
///
/// pub fn example() {
/// let stream = generators.seed_pcg32(5, 1)
/// let bools =
/// random.bools(10, stream)
/// |> pair.first()
/// }
/// </details>
///
/// <div style="text-align: right;">
/// <a href="#">
/// <small>Back to top ↑</small>
/// </a>
/// </div>
///
pub fn bools(
m: Int,
stream: iterator.Iterator(Int),
) -> Result(#(List(Bool), iterator.Iterator(Int)), String) {
case m > 0 {
False ->
"Invalid input arugment: m < 0. Valid input is m > 0."
|> Error
True -> {
// Take out 'm' integers from the stream of pseudo-random numbers and generate
// uniform random numbers.
assert Ok(out) = uniform.uniform_random(stream, 0., 1., m)
let bools_list =
pair.first(out)
|> list.map(fn(x: Float) -> Bool {
case x <=. 0.5 {
True -> True
False -> False
}
})
#(bools_list, pair.second(out))
|> Ok
}
}
}