diff --git a/vlib/arrays/arrays.v b/vlib/arrays/arrays.v new file mode 100644 index 0000000000..8dab3b4409 --- /dev/null +++ b/vlib/arrays/arrays.v @@ -0,0 +1,118 @@ +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] +pub fn min(a []T) T { + if a.len==0 { panic('.min called on an empty array') } + mut val := a[0] + for i in 0..a.len { + if a[i] < val { + val = a[i] + } + } + return val +} + +// max returns the maximum +[direct_array_access] +pub fn max(a []T) T { + if a.len==0 { panic('.max called on an empty array') } + mut val := a[0] + for i in 0..a.len { + if a[i] > val { + val = a[i] + } + } + return val +} + +// idx_min returns the index of the first minimum +[direct_array_access] +pub fn idx_min(a []T) int { + if a.len==0 { panic('.idxmin called on an empty array') } + mut idx := 0 + mut val := a[0] + for i in 0..a.len { + if a[i] < val { + val = a[i] + idx = i + } + } + return idx +} + +// idx_max returns the index of the first maximum +[direct_array_access] +pub fn idx_max(a []T) int { + if a.len==0 { panic('.idxmax called on an empty array') } + mut idx := 0 + mut val := a[0] + for i in 0..a.len { + if a[i] > val { + val = a[i] + idx = i + } + } + return idx +} + +// shuffle randomizes the first n items of an array in place (all if n=0) +[direct_array_access] +pub fn shuffle(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(a []T, b []T) []T { + mut m := []T{len:a.len + b.len} + mut ia := 0 + mut ib := 0 + mut j := 0 + + // TODO efficient approach to merge_desc where: a[ia] >= b[ib] + for ia(a)==2 + assert min(a[2..])==4 + + b := [f32(5.1), 3.1, 1.1, 9.1] + assert min(b) == f32(1.1) + assert min(b[..2]) == f32(3.1) + + c := [byte(4), 9, 3, 1] + assert min(c) == byte(1) + assert min(c[..3]) == byte(3) +} + + +fn test_max() { + a := [8, 2, 6, 4] + assert max(a)==8 + assert max(a[1..])==6 + + b := [f32(5.1), 3.1, 1.1, 9.1] + assert max(b) == f32(9.1) + assert max(b[..3]) == f32(5.1) + + c := [byte(4), 9, 3, 1] + assert max(c) == byte(9) + assert max(c[2..]) == byte(3) +} + + +fn test_idx_min() { + a := [8, 2, 6, 4] + assert idx_min(a)==1 + + b := [f32(5.1), 3.1, 1.1, 9.1] + assert idx_min(b) == 2 + + c := [byte(4), 9, 3, 1] + assert idx_min(c) == 3 +} + + +fn test_idx_max() { + a := [8, 2, 6, 4] + assert idx_max(a)==0 + + b := [f32(5.1), 3.1, 1.1, 9.1] + assert idx_max(b) == 3 + + c := [byte(4), 9, 3, 1] + assert idx_max(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(mut b, 0) + 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() + 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() + 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] + shuffle(mut f,0) + assert f == []int{} +} + +fn test_merge() { + a := [1,3,5,5,7] + b := [2,4,4,5,6,8] + c := []int{} + d := []int{} + assert merge(a,b) == [1,2,3,4,4,5,5,5,6,7,8] + assert merge(c,d) == [] + assert merge(a,c) == a + assert merge(d,b) == b +}