rand: move the shuffle function from `arrays` to `rand.util` (#8587)

pull/8593/head^2
Subhomoy Haldar 2021-02-05 23:54:38 +05:30 committed by GitHub
parent ed6fc79fbe
commit 9a1da1a97b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 45 deletions

View File

@ -3,9 +3,7 @@ module arrays
// Common arrays functions:
// - min / max - return the value of the minumum / maximum
// - idx_min / idx_max - return the index of the first minumum / maximum
// - shuffle - randomize array items order in place (allowing exit after n items)
// - merge - combine two sorted arrays and maintain sorted order
import rand
// min returns the minimum
[direct_array_access]
@ -71,22 +69,6 @@ pub fn idx_max<T>(a []T) int {
return idx
}
// shuffle randomizes the first n items of an array in place (all if n=0)
[direct_array_access]
pub fn shuffle<T>(mut a []T, n int) {
if n < 0 || n > a.len {
panic("shuffle's argument 'n' must be in range [0,a.len]")
}
cnt := if n == 0 { a.len - 1 } else { n }
for i in 0 .. cnt {
x := rand.int_in_range(i, a.len)
// swap
a_i := a[i]
a[i] = a[x]
a[x] = a_i
}
}
// merge two sorted arrays (ascending) and maintain sorted order
[direct_array_access]
pub fn merge<T>(a []T, b []T) []T {
@ -119,3 +101,8 @@ pub fn merge<T>(a []T, b []T) []T {
}
return m
}
[deprecated]
pub fn shuffle<T>(mut a []T, n int) {
panic('Please use rand.util.shuffle() instead')
}

View File

@ -44,31 +44,6 @@ fn test_idx_max() {
assert idx_max<byte>(c) == 1
}
fn test_shuffle() {
rand.seed([u32(1), 2]) // set seed to produce same results in order
a := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
mut b := a.clone()
mut c := a.clone()
shuffle<int>(mut b, 0)
shuffle<int>(mut c, 0)
assert b == [6, 4, 5, 1, 9, 2, 10, 3, 8, 7]
assert c == [1, 6, 5, 8, 7, 2, 10, 9, 3, 4]
// test shuffling a slice
mut d := a.clone()
shuffle<int>(mut d[..5], 0)
assert d == [5, 2, 1, 3, 4, 6, 7, 8, 9, 10]
assert d[5..] == a[5..]
// test shuffling n items
mut e := a.clone()
shuffle<int>(mut e, 5)
assert e[..5] == [10, 3, 1, 8, 4]
assert e[5..] == [6, 7, 5, 9, 2]
// test shuffling empty array
mut f := a[..0]
shuffle<int>(mut f, 0)
assert f == []int{}
}
fn test_merge() {
a := [1, 3, 5, 5, 7]
b := [2, 4, 4, 5, 6, 8]

View File

@ -4,7 +4,6 @@
module util
import rand
import arrays
// sample_nr returns a sample of the array without replacement. 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. Note that if the array has repeating elements, then the sample may have repeats as well.
pub fn sample_nr<T>(array []T, k int) []T {
@ -18,7 +17,7 @@ pub fn sample_nr<T>(array []T, k int) []T {
for i, mut v in indices {
v = i
}
arrays.shuffle<int>(mut indices, k)
shuffle(mut indices, k)
for i in 0 .. k {
results[i] = array[indices[i]]
}
@ -34,3 +33,19 @@ pub fn sample_r<T>(array []T, k int) []T {
}
return results
}
// shuffle randomizes the first `n` items of an array in place (all if `n` is 0)
[direct_array_access]
pub fn shuffle<T>(mut a []T, n int) {
if n < 0 || n > a.len {
panic("argument 'n' must be in range [0, a.len]")
}
cnt := if n == 0 { a.len - 1 } else { n }
for i in 0 .. cnt {
x := rand.int_in_range(i, a.len)
// swap
a_i := a[i]
a[i] = a[x]
a[x] = a_i
}
}

View File

@ -1,3 +1,4 @@
import rand
import rand.util
fn test_sample_nr() {
@ -29,3 +30,28 @@ fn test_sample_r() {
assert element in a
}
}
fn test_shuffle() {
rand.seed([u32(1), 2]) // set seed to produce same results in order
a := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
mut b := a.clone()
mut c := a.clone()
util.shuffle(mut b, 0)
util.shuffle(mut c, 0)
assert b == [6, 4, 5, 1, 9, 2, 10, 3, 8, 7]
assert c == [1, 6, 5, 8, 7, 2, 10, 9, 3, 4]
// test shuffling a slice
mut d := a.clone()
util.shuffle(mut d[..5], 0)
assert d == [5, 2, 1, 3, 4, 6, 7, 8, 9, 10]
assert d[5..] == a[5..]
// test shuffling n items
mut e := a.clone()
util.shuffle(mut e, 5)
assert e[..5] == [10, 3, 1, 8, 4]
assert e[5..] == [6, 7, 5, 9, 2]
// test shuffling empty array
mut f := a[..0]
util.shuffle(mut f, 0)
assert f == []int{}
}