Name | Executed | Routines | % | Executed | Lines | % | Unexecuted |
/home/matt/eu/rds/include/std/rand.e | 6 | 7 | 85.71% | 35 | 57 | 61.40% | 22 |
Routine | Executed | Lines | Unexecuted | |
sample() | 0 | 20 | 0.00% | 20 |
roll() | 7 | 9 | 77.78% | 2 |
chance() | 2 | 2 | 100.00% | 0 |
rand_range() | 8 | 8 | 100.00% | 0 |
rnd() | 9 | 9 | 100.00% | 0 |
rnd_1() | 5 | 5 | 100.00% | 0 |
set_rand() | 3 | 3 | 100.00% | 0 |
# | Executed | |
1 | -- (c) Copyright - See License.txt | |
2 | -- | |
3 | ||
4 | namespace random | |
5 | ||
6 | --**** | |
7 | -- == Random Numbers | |
8 | -- | |
9 | -- < | |
10 | -- | |
11 | ||
12 | --**** | |
13 | -- Signature: | |
14 | -- | |
15 | -- | |
16 | -- Description: | |
17 | -- Return a random positive integer. | |
18 | -- | |
19 | -- Parameters: | |
20 | -- # ##maximum## : an atom, a cap on the value to return. | |
21 | -- | |
22 | -- Returns: | |
23 | -- An **integer**, from 1 to ##maximum##. | |
24 | -- | |
25 | -- Errors: | |
26 | -- If [[:ceil]](##maximum##) is not a positive integer <= 1073741823, | |
27 | -- an error will occur. It must also be at least 1. | |
28 | -- | |
29 | -- Comments: | |
30 | -- This function may be applied to an atom or to all elements of a sequence. | |
31 | -- In order to get reproducible results from this function, you should call | |
32 | -- [[:set_rand]]() with a reproducible value prior. | |
33 | -- | |
34 | -- Example 1: | |
35 | -- | |
36 | -- s = rand({10, 20, 30}) | |
37 | -- -- s might be: {5, 17, 23} or {9, 3, 12} etc. | |
38 | -- | |
39 | -- | |
40 | -- See Also: | |
41 | -- [[:set_rand]], [[:ceil]] | |
42 | ||
43 | ||
44 | --** | |
45 | -- Return a random integer from a specified inclusive integer range. | |
46 | -- | |
47 | -- Parameters: | |
48 | -- # ##lo## : an integer, the lower bound of the range | |
49 | -- # ##hi## : an integer, the upper bound of the range. | |
50 | -- | |
51 | -- Returns: | |
52 | -- An **integer**, randomly drawn between ##lo## and ##hi## inclusive. | |
53 | -- | |
54 | -- Errors: | |
55 | -- If ##lo## is not less than ##hi##, an error will occur. | |
56 | -- | |
57 | -- Comments: | |
58 | -- This function may be applied to an atom or to all elements of a sequence. | |
59 | -- In order to get reproducible results from this function, you should | |
60 | -- call ##set_rand##() with a reproducible value prior. | |
61 | -- | |
62 | -- Example 1: | |
63 | -- | |
64 | -- s = rand_range(18, 24) | |
65 | -- -- s could be any of: 18, 19, 20, 21, 22, 23 or 24 | |
66 | -- | |
67 | -- | |
68 | -- See Also: | |
69 | -- [[:rand]], [[:set_rand]], [[:rnd]] | |
70 | ||
71 | 35 | |
72 | ||
73 | 35 | if lo > hi then |
74 | 1 | integer temp = hi |
75 | 1 | hi = lo |
76 | 1 | lo = temp |
77 | end if | |
78 | ||
79 | 35 | lo -= 1 |
80 | 35 | hi -= lo |
81 | ||
82 | 35 | return lo + rand(hi) |
83 | end function | |
84 | ||
85 | 101 | constant M_SET_RAND = 35 |
86 | ||
87 | --** | |
88 | -- Return a random floating point number in the range 0 to 1. | |
89 | -- | |
90 | -- Parameters: | |
91 | -- None. | |
92 | -- | |
93 | -- Returns: | |
94 | -- An **atom**, randomly drawn between 0.0 and 1.0 inclusive. | |
95 | -- | |
96 | -- Comments: | |
97 | -- In order to get reproducible results from this function, you should | |
98 | -- call ##set_rand##() with a reproducible value prior to calling this. | |
99 | -- | |
100 | -- Example 1: | |
101 | -- | |
102 | -- set_rand(1001) | |
103 | -- s = rnd() | |
104 | -- -- s is 0.2634879318 | |
105 | -- | |
106 | -- | |
107 | -- See Also: | |
108 | -- [[:rand]], [[:set_rand]], [[:rand_range]] | |
109 | ||
110 | 10010 | |
111 | atom a,b,r | |
112 | ||
113 | 10010 | a = rand(#3FFFFFFF) |
114 | 10010 | if a = 1 then return 0 end if |
115 | 10010 | b = rand(#3FFFFFFF) |
116 | 10010 | if b = 1 then return 0 end if |
117 | 10010 | if a > b then |
118 | 4988 | r = b / a |
119 | else | |
120 | 5022 | r = a / b |
121 | end if | |
122 | ||
123 | 10010 | return r |
124 | end function | |
125 | ||
126 | --** | |
127 | -- Return a random floating point number in the range 0 to less than 1. | |
128 | -- | |
129 | -- Parameters: | |
130 | -- None. | |
131 | -- | |
132 | -- Returns: | |
133 | -- An **atom**, randomly drawn between 0.0 and a number less than 1.0 | |
134 | -- | |
135 | -- Comments: | |
136 | -- In order to get reproducible results from this function, you should | |
137 | -- call ##set_rand##() with a reproducible value prior to calling this. | |
138 | -- | |
139 | -- Example 1: | |
140 | -- | |
141 | -- set_rand(1001) | |
142 | -- s = rnd_1() | |
143 | -- -- s is 0.2634879318 | |
144 | -- | |
145 | -- | |
146 | -- See Also: | |
147 | -- [[:rand]], [[:set_rand]], [[:rand_range]] | |
148 | ||
149 | 10001 | |
150 | atom r | |
151 | ||
152 | 10001 | while r >= 1.0 with entry do |
153 | entry | |
154 | 10001 | r = rnd() |
155 | 10001 | end while |
156 | 10001 | return r |
157 | end function | |
158 | ||
159 | --** | |
160 | -- Reset the random number generator. | |
161 | -- | |
162 | -- Parameters: | |
163 | -- # ##seed## : an object. The generator uses this initialize itself for the next | |
164 | -- random number generated. This can be a single integer or atom, | |
165 | -- or a sequence of two integers, or an empty sequence or any | |
166 | -- other sort of sequence. | |
167 | -- | |
168 | -- Comments: | |
169 | -- * Starting from a ##seed##, the values returned by ##rand##() are | |
170 | -- reproducible. This is useful for demos and stress tests based on random | |
171 | -- data. Normally the numbers returned by the ##rand##() function are totally | |
172 | -- unpredictable, and will be different each time you run your program. | |
173 | -- Sometimes however you may wish to repeat the same series of numbers, | |
174 | -- perhaps because you are trying to debug your program, or maybe you want | |
175 | -- the ability to generate the same output (e.g. a random picture) for your | |
176 | -- user upon request. | |
177 | -- * Internally there are actually two seed values. | |
178 | -- ** When ##set_rand()## is called with a single integer or atom, the two | |
179 | -- internal seeds are derived from the parameter. | |
180 | -- ** When ##set_rand()## is called with a sequence of exactly two integers/atoms | |
181 | -- the internal seeds are set to the parameter values. | |
182 | -- ** When ##set_rand()## is called with an empty sequence, the internal seeds are | |
183 | -- set to random values and are unpredictable. This is how to reset the generator. | |
184 | -- ** When ##set_rand()## is called with any other sequence, the internal seeds are | |
185 | -- set based on the length of the sequence and the hashed value of the sequence. | |
186 | -- * Aside from an empty ##seed## parameter, this sets the generator to a known state | |
187 | -- and the random numbers generated after come in a predicable order, though they still | |
188 | -- appear to be random. | |
189 | -- | |
190 | -- Example 1: | |
191 | -- | |
192 | -- sequence s, t | |
193 | -- s = repeat(0, 3) | |
194 | -- t = s | |
195 | -- | |
196 | -- set_rand(12345) | |
197 | -- s[1] = rand(10) | |
198 | -- s[2] = rand(100) | |
199 | -- s[3] = rand(1000) | |
200 | -- | |
201 | -- set_rand(12345) -- same value for set_rand() | |
202 | -- t[1] = rand(10) -- same arguments to rand() as before | |
203 | -- t[2] = rand(100) | |
204 | -- t[3] = rand(1000) | |
205 | -- -- at this point s and t will be identical | |
206 | -- set_rand("") -- Reset the generator to an unknown seed. | |
207 | -- t[1] = rand(10) -- Could be anything now, no way to predict it. | |
208 | -- | |
209 | -- | |
210 | -- See Also: | |
211 | -- [[:rand]] | |
212 | ||
213 | 10 | |
214 | -- A given value of seed will cause the same series of | |
215 | -- random numbers to be generated from the rand() function | |
216 | 10 | machine_proc(M_SET_RAND, seed) |
217 | 10 | end procedure |
218 | ||
219 | --** | |
220 | -- Simulates the probability of a desired outcome. | |
221 | -- | |
222 | -- Parameters: | |
223 | -- # ##my_limit## : an atom. The desired chance of something happening. | |
224 | -- # ##top_limit##: an atom. The maximum chance of something happening. The | |
225 | -- default is 100. | |
226 | -- | |
227 | -- Returns: | |
228 | -- an integer. 1 if the desired chance happened otherwise 0. | |
229 | -- | |
230 | -- Comments: | |
231 | -- This simulates the chance of something happening. For example, if you | |
232 | -- wnat something to happen with a probablity of 25 times out of 100 times then you code ##chance(25)## | |
233 | -- and if you want something to (most likely) occur 345 times out of 999 times, you code | |
234 | -- ##chance(345, 999)###. | |
235 | -- | |
236 | -- Example 1: | |
237 | -- | |
238 | -- -- 65% of the days are sunny, so ... | |
239 | -- if chance(65) then | |
240 | -- puts(1, "Today will be a sunny day") | |
241 | -- elsif chance(40) then | |
242 | -- -- And 40% of non-sunny days it will rain. | |
243 | -- puts(1, "It will rain today") | |
244 | -- else | |
245 | -- puts(1, "Today will be a overcast day") | |
246 | -- end if | |
247 | -- | |
248 | -- | |
249 | -- See Also: | |
250 | -- [[:rnd]], [[:roll]] | |
251 | 10000 | |
252 | 10000 | return (rnd_1() * top_limit) <= my_limit |
253 | end function | |
254 | ||
255 | ||
256 | --** | |
257 | -- Simulates the probability of a dice throw. | |
258 | -- | |
259 | -- Parameters: | |
260 | -- # ##desired## : an object. One or more desired outcomes. | |
261 | -- # ##sides##: an integer. The number of sides on the dice. Default is 6. | |
262 | -- | |
263 | -- Returns: | |
264 | -- an integer. 0 if none of the desired outcomes occured, otherwise | |
265 | -- the face number that was rolled. | |
266 | -- | |
267 | -- Comments: | |
268 | -- The minimum number of sides is 2 and there is no maximum. | |
269 | -- | |
270 | -- Example 1: | |
271 | -- | |
272 | -- res = roll(1, 2) -- Simulate a coin toss. | |
273 | -- res = roll({1,6}) -- Try for a 1 or a 6 from a standard die toss. | |
274 | -- res = roll({1,2,3,4}, 20) -- Looking for any number under 5 from a 20-sided die. | |
275 | -- | |
276 | -- | |
277 | -- See Also: | |
278 | -- [[:rnd]], [[:chance]] | |
279 | 10000 | |
280 | integer rolled | |
281 | 10000 | if sides < 2 then |
282 | 0 | return 0 |
283 | end if | |
284 | 10000 | if atom(desired) then |
285 | 0 | desired = {desired} |
286 | end if | |
287 | ||
288 | 10000 | rolled = find( rand(sides), desired) |
289 | 10000 | if rolled then |
290 | 1507 | return desired[rolled] |
291 | else | |
292 | 8493 | return 0 |
293 | end if | |
294 | end function | |
295 | ||
296 | --** | |
297 | -- Selects a random sample sub-set of items from a population set. | |
298 | -- | |
299 | -- Parameters: | |
300 | -- # ##full_set## : a sequence. The set of items from which to take a sample. | |
301 | -- # ##sample_size##: an integer. The number of samples to take. | |
302 | -- # ##return_remaining##: an integer. If non-zero, the sub-set not selected is also returned. | |
303 | -- If zero, the default, only the sampled set is returned. | |
304 | -- | |
305 | -- Returns: | |
306 | -- a sequence. When ##return_remaining## = 0 then this is the set of samples, otherwise | |
307 | -- it returns a two-element sequence; the first is the samples, and the second | |
308 | -- is the remainder of the population (in the original order). | |
309 | -- | |
310 | -- Comments: | |
311 | -- * If ##sample_size## is less than 1, an empty set is returned. | |
312 | -- * If ##sample_size## is greater than or equal to the population count, | |
313 | -- the entire population set is returned, but in a random order. | |
314 | -- | |
315 | -- Example 1: | |
316 | -- | |
317 | -- set_rand("example") | |
318 | -- printf(1, "%s\n", { sample("abcdefghijklmnopqrstuvwxyz", 1)}) --> "t" | |
319 | -- printf(1, "%s\n", { sample("abcdefghijklmnopqrstuvwxyz", 5)}) --> "flukq" | |
320 | -- printf(1, "%s\n", { sample("abcdefghijklmnopqrstuvwxyz", -1)}) --> "" | |
321 | -- printf(1, "%s\n", { sample("abcdefghijklmnopqrstuvwxyz", 26)}) --> "kghrsxmjoeubaywlzftcpivqnd" | |
322 | -- printf(1, "%s\n", { sample("abcdefghijklmnopqrstuvwxyz", 25)}) --> "omntrqsbjguaikzywvxflpedc" | |
323 | -- | |
324 | -- | |
325 | -- Example 2: | |
326 | -- | |
327 | -- -- Deal 4 hands of 5 cards from a standard deck of cards. | |
328 | -- sequence theDeck | |
329 | -- sequence hands = {} | |
330 | -- sequence rt | |
331 | -- function new_deck() | |
332 | -- sequence nd = {} | |
333 | -- for i = 1 to 4 do | |
334 | -- for j = 1 to 13 do | |
335 | -- nd = append(nd, {i,j}) | |
336 | -- end for | |
337 | -- end for | |
338 | -- return nd | |
339 | -- end function | |
340 | -- theDeck = new_deck() | |
341 | -- for i = 1 to 4 do | |
342 | -- rt = sample(theDeck, 5, 1) | |
343 | -- theDeck = rt[2] | |
344 | -- hands = append(hands, rt[1]) | |
345 | -- end for | |
346 | -- | |
347 | -- | |
348 | 0 | |
349 | sequence lResult | |
350 | integer lIdx | |
351 | integer lChoice | |
352 | integer lLen | |
353 | ||
354 | 0 | if sample_size < 1 then |
355 | 0 | if return_remaining then |
356 | 0 | return {{}, full_set} |
357 | else | |
358 | 0 | return {} |
359 | end if | |
360 | end if | |
361 | ||
362 | 0 | if sample_size >= length(full_set) then |
363 | 0 | sample_size = length(full_set) |
364 | end if | |
365 | ||
366 | 0 | lResult = repeat(0, sample_size) |
367 | 0 | lIdx = 0 |
368 | 0 | lLen = length(full_set) |
369 | 0 | while lIdx < sample_size do |
370 | 0 | lChoice = rand(lLen) |
371 | 0 | lIdx += 1 |
372 | 0 | lResult[lIdx] = full_set[lChoice] |
373 | 0 | lLen -= 1 |
374 | 0 | full_set[lChoice .. $-1] = full_set[lChoice+1 .. $] |
375 | 0 | end while |
376 | ||
377 | 0 | if return_remaining then |
378 | 0 | return {lResult, full_set[1 .. $ - sample_size]} |
379 | else | |
380 | 0 | return lResult |
381 | end if | |
382 | end function |