From f5c4671bfbad96bf346bd7e9a21fc4317b4959df Mon Sep 17 00:00:00 2001 From: Indrajith K L Date: Sat, 3 Dec 2022 17:00:20 +0530 Subject: Adds most of the tools --- v_windows/v/vlib/rand/util/util.v | 52 +++++++++++++++++++++++++++++++ v_windows/v/vlib/rand/util/util_test.v | 57 ++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 v_windows/v/vlib/rand/util/util.v create mode 100644 v_windows/v/vlib/rand/util/util_test.v (limited to 'v_windows/v/vlib/rand/util') diff --git a/v_windows/v/vlib/rand/util/util.v b/v_windows/v/vlib/rand/util/util.v new file mode 100644 index 0000000..e1c30ca --- /dev/null +++ b/v_windows/v/vlib/rand/util/util.v @@ -0,0 +1,52 @@ +// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. +module util + +import rand + +// 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(array []T, k int) []T { + n := array.len + if k > n { + panic('Cannot sample $k elements without replacement from a $n-element array.') + } + mut results := []T{len: k} + mut indices := []int{len: n} + // Initialize with all indices + // temporary workaround for issue #10343 + for i in 0 .. indices.len { + indices[i] = i + } + shuffle(mut indices, k) + for i in 0 .. k { + results[i] = array[indices[i]] + } + return results +} + +// sample_r returns a sample of the array with replacement. This means the elements can repeat and the size of the sample may exceed the size of the array +pub fn sample_r(array []T, k int) []T { + n := array.len + mut results := []T{len: k} + for i in 0 .. k { + results[i] = array[rand.intn(n)] + } + return results +} + +// shuffle randomizes the first `n` items of an array in place (all if `n` is 0) +[direct_array_access] +pub fn shuffle(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 + } +} diff --git a/v_windows/v/vlib/rand/util/util_test.v b/v_windows/v/vlib/rand/util/util_test.v new file mode 100644 index 0000000..f92e70b --- /dev/null +++ b/v_windows/v/vlib/rand/util/util_test.v @@ -0,0 +1,57 @@ +import rand +import rand.util + +fn test_sample_nr() { + lengths := [1, 3, 4, 5, 6, 7] + a := ['one', 'two', 'three', 'four', 'five', 'six', 'seven'] + for length in lengths { + b := util.sample_nr(a, length) + assert b.len == length + for element in b { + assert element in a + // make sure every element occurs once + mut count := 0 + for e in b { + if e == element { + count++ + } + } + assert count == 1 + } + } +} + +fn test_sample_r() { + k := 20 + a := ['heads', 'tails'] + b := util.sample_r(a, k) + assert b.len == k + for element in b { + 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{} +} -- cgit v1.2.3