1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
# implement and test functional primitives: map, grep and sort.
puts '1..9'
test_counter = 0
def is(result, expected, description)
test_num = (test_counter += 1)
passed = result eq expected
puts "#{passed ? 'ok' : 'nok'} #{test_num} - #{description}"
puts "# expected:'#{expected}' got:'#{result}'" \
unless passed
passed
end
def dump(arr, idx = 1)
arr[idx-1] ~ (idx < arr ? ',' ~ dump(arr, idx+1) : '')
end
# ------------
def grep(array_inp, &selector)
array_out = []
n = -1
selector = lambda {|elem| !elem.nil? && elem} \
if selector.nil?
for elem in array_inp ;
array_out[ n+=1 ] = elem \
if selector.call(elem)
end
array_out
end
arr = [0, 2, 10, 1, 13, 27, 5, 4, 18]
is dump(arr), '0,2,10,1,13,27,5,4,18', 'array dump sanity'
even = grep(arr) {|n| n % 2 == 0}
is dump(even), '0,2,10,4,18', 'grep [even]'
arr1 = nqp::clone(arr)
nqp::push(arr1, nil)
is dump( grep(arr1) ), '2,10,1,13,27,5,4,18', 'grep [default]'
# ------------
def map(array_inp, &mapper)
array_out = []
n = -1
for elem in array_inp do
mapping = mapper.call(elem)
if nqp::islist(mapping) then
# flatten sublists
for sub_elem in mapping ;
array_out[ n+=1 ] = sub_elem
end
else
array_out[ n+=1 ] = mapping
end
end
array_out
end
squares = map(arr) {|n| n * n}
is dump(squares), '0,4,100,1,169,729,25,16,324', 'map [squares]'
# ------------
def sort(list, &func) ;
list = nqp::clone list # take a copy
func = lambda {|a,b| a cmp b} \
if func.nil?
_quicksort(list, 0, nqp::elems(list)-1, &func);
end
def _quicksort(list, p, r, &func)
if p < r then
q = _partition(list, p, r, &func)
_quicksort(list, p, q-1, &func)
_quicksort(list, q+1, r, &func)
end
list
end
def _partition(list, p, r, &func)
pivot = list[r]
i = j = p - 1
while (j += 1) < r
_swap(list, i += 1, j) \
if 0 <= func.call(pivot, list[j])
end
_swap(list, i += 1, r)
i
end
def _swap(list, i, j)
tmp = list[i]
list[i] = list[j]
list[j] = tmp
end
str_sort = sort(arr)
is dump(str_sort), '0,1,10,13,18,2,27,4,5', 'sort [default]'
num_sort = sort(arr) {|a,b| a <=> b}
is dump(num_sort), '0,1,2,4,5,10,13,18,27', 'sort [numeric]'
# ------------
# put it all together
odd = lambda {|n| n % 2 == 1}
combined = map(sort grep(arr,&odd)) {|str| nqp::flip(str)}
is dump(combined), '1,31,72,5', 'combined map sort grep'
splitter = lambda {|n| nqp::split('',n)}
is dump( map(combined, &splitter) ), '1,3,1,7,2,5', 'map [flattening]'
is dump(arr), '0,2,10,1,13,27,5,4,18', 'array readonly'
|