@@ -274,6 +274,76 @@ pub fn (mut rng PRNG) ascii(len int) string {
274
274
return internal_string_from_set (mut rng, rand.ascii_chars, len)
275
275
}
276
276
277
+ // Configuration struct for the shuffle functions.
278
+ // The start index is inclusive and the end index is exclusive.
279
+ // Set the end to 0 to shuffle until the end of the array.
280
+ [params]
281
+ pub struct ShuffleConfigStruct {
282
+ pub :
283
+ start int
284
+ end int
285
+ }
286
+
287
+ fn (config ShuffleConfigStruct) validate_for <T >(a []T) ? {
288
+ if config.start < 0 || config.start > = a.len {
289
+ return error ("argument 'config.start' must be in range [0, a.len)" )
290
+ }
291
+ if config.end < 0 || config.end > a.len {
292
+ return error ("argument 'config.end' must be in range [0, a.len]" )
293
+ }
294
+ }
295
+
296
+ // shuffle randomly permutates the elements in `a`. The range for shuffling is
297
+ // optional and the entire array is shuffled by default. Leave the end as 0 to
298
+ // shuffle all elements until the end.
299
+ [direct_array_access ]
300
+ pub fn (mut rng PRNG) shuffle <T >(mut a []T, config ShuffleConfigStruct) ? {
301
+ config.validate_for (a) ?
302
+ new_end := if config.end == 0 { a.len } else { config.end }
303
+ for i in config.start .. new_end {
304
+ x := rng.int_in_range (i, new_end) or { config.start }
305
+ // swap
306
+ a_i := a[i]
307
+ a[i] = a[x]
308
+ a[x] = a_i
309
+ }
310
+ }
311
+
312
+ // shuffle_clone returns a random permutation of the elements in `a`.
313
+ // The permutation is done on a fresh clone of `a`, so `a` remains unchanged.
314
+ pub fn (mut rng PRNG) shuffle_clone <T >(a []T, config ShuffleConfigStruct) ? []T {
315
+ mut res := a.clone ()
316
+ rng.shuffle (mut res, config) ?
317
+ return res
318
+ }
319
+
320
+ // choose samples k elements from the array without replacement.
321
+ // This means the indices cannot repeat and it restricts the sample size to be less than or equal to the size of the given array.
322
+ // Note that if the array has repeating elements, then the sample may have repeats as well.
323
+ pub fn (mut rng PRNG) choose <T >(array []T, k int ) ? []T {
324
+ n := array.len
325
+ if k > n {
326
+ return error ('Cannot choose $k elements without replacement from a $n -element array.' )
327
+ }
328
+ mut results := []T{len: k}
329
+ mut indices := []int {len: n, init: it }
330
+ rng.shuffle (mut indices) ?
331
+ for i in 0 .. k {
332
+ results[i] = array[indices[i]]
333
+ }
334
+ return results
335
+ }
336
+
337
+ // sample samples k elements from the array with replacement.
338
+ // This means the elements can repeat and the size of the sample may exceed the size of the array.
339
+ pub fn (mut rng PRNG) sample <T >(array []T, k int ) []T {
340
+ mut results := []T{len: k}
341
+ for i in 0 .. k {
342
+ results[i] = array[rng.intn (array.len) or { 0 }]
343
+ }
344
+ return results
345
+ }
346
+
277
347
__global default_rng & PRNG
278
348
279
349
// new_default returns a new instance of the default RNG. If the seed is not provided, the current time will be used to seed the instance.
@@ -440,17 +510,17 @@ const (
440
510
// users or business transactions.
441
511
// (https://news.ycombinator.com/item?id=14526173)
442
512
pub fn ulid () string {
443
- return internal_ulid_at_millisecond ( mut default_rng, u64 (time. utc (). unix_time_milli ()) )
513
+ return default_rng. ulid ( )
444
514
}
445
515
446
516
// ulid_at_millisecond does the same as `ulid` but takes a custom Unix millisecond timestamp via `unix_time_milli`.
447
517
pub fn ulid_at_millisecond (unix_time_milli u64 ) string {
448
- return internal_ulid_at_millisecond ( mut default_rng, unix_time_milli)
518
+ return default_rng. ulid_at_millisecond ( unix_time_milli)
449
519
}
450
520
451
521
// string_from_set returns a string of length `len` containing random characters sampled from the given `charset`
452
522
pub fn string_from_set (charset string , len int ) string {
453
- return internal_string_from_set ( mut default_rng, charset, len)
523
+ return default_rng. string_from_set ( charset, len)
454
524
}
455
525
456
526
// string returns a string of length `len` containing random characters in range `[a-zA-Z]`.
@@ -468,19 +538,28 @@ pub fn ascii(len int) string {
468
538
return string_from_set (rand.ascii_chars, len)
469
539
}
470
540
471
- // shuffle randomly permutates the elements in `a`.
472
- pub fn shuffle <T >(mut a []T) {
473
- len := a.len
474
- for i in 0 .. len {
475
- si := i + intn (len - i) or { len }
476
- a[si], a[i] = a[i], a[si]
477
- }
541
+ // shuffle randomly permutates the elements in `a`. The range for shuffling is
542
+ // optional and the entire array is shuffled by default. Leave the end as 0 to
543
+ // shuffle all elements until the end.
544
+ pub fn shuffle <T >(mut a []T, config ShuffleConfigStruct) ? {
545
+ default_rng.shuffle (mut a, config) ?
478
546
}
479
547
480
548
// shuffle_clone returns a random permutation of the elements in `a`.
481
549
// The permutation is done on a fresh clone of `a`, so `a` remains unchanged.
482
- pub fn shuffle_clone <T >(a []T) []T {
483
- mut res := a.clone ()
484
- shuffle (mut res)
485
- return res
550
+ pub fn shuffle_clone <T >(a []T, config ShuffleConfigStruct) ? []T {
551
+ return default_rng.shuffle_clone (a, config)
552
+ }
553
+
554
+ // choose samples k elements from the array without replacement.
555
+ // This means the indices cannot repeat and it restricts the sample size to be less than or equal to the size of the given array.
556
+ // Note that if the array has repeating elements, then the sample may have repeats as well.
557
+ pub fn choose <T >(array []T, k int ) ? []T {
558
+ return default_rng.choose (array, k)
559
+ }
560
+
561
+ // sample samples k elements from the array with replacement.
562
+ // This means the elements can repeat and the size of the sample may exceed the size of the array.
563
+ pub fn sample <T >(array []T, k int ) []T {
564
+ return default_rng.sample (array, k)
486
565
}
0 commit comments