rand: add `pub fn shuffle<T>(mut a []T) {` function + tests (#13811)

pull/13758/head^2
Nick Treleaven 2022-03-23 13:31:26 +00:00 committed by GitHub
parent 35cd8112a5
commit 2e963e36ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 0 deletions

View File

@ -467,3 +467,20 @@ pub fn hex(len int) string {
pub fn ascii(len int) string { pub fn ascii(len int) string {
return string_from_set(rand.ascii_chars, len) return string_from_set(rand.ascii_chars, len)
} }
// shuffle randomly permutates the elements in `a`.
pub fn shuffle<T>(mut a []T) {
len := a.len
for i in 0 .. len {
si := i + intn(len - i) or { len }
a[si], a[i] = a[i], a[si]
}
}
// shuffle_clone returns a random permutation of the elements in `a`.
// The permutation is done on a fresh clone of `a`, so `a` remains unchanged.
pub fn shuffle_clone<T>(a []T) []T {
mut res := a.clone()
shuffle(mut res)
return res
}

View File

@ -317,3 +317,55 @@ fn test_new_global_rng() {
rand.set_rng(old) rand.set_rng(old)
} }
fn test_shuffle() {
mut arrays := [][]int{}
arrays << [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
arrays << [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
for seed in seeds {
a := get_n_random_ints(seed, 10)
arrays << a
}
//
mut digits := []map[int]int{len: 10}
for digit in 0 .. 10 {
digits[digit] = {}
for idx in 0 .. 10 {
digits[digit][idx] = 0
}
}
for mut a in arrays {
o := a.clone()
for _ in 0 .. 100 {
rand.shuffle(mut a)
assert *a != o
for idx in 0 .. 10 {
digits[idx][a[idx]]++
}
}
}
for digit in 1 .. 10 {
assert digits[0] != digits[digit]
}
for digit in 0 .. 10 {
for idx in 0 .. 10 {
assert digits[digit][idx] > 10
}
// eprintln('digits[$digit]: ${digits[digit]}')
}
}
fn test_shuffle_clone() {
original := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
mut a := original.clone()
mut results := [][]int{}
for _ in 0 .. 10 {
results << rand.shuffle_clone(a)
}
assert original == a
for idx in 1 .. 10 {
assert results[idx].len == 10
assert results[idx] != results[0]
assert results[idx] != original
}
}