2017-06-26 12:15:03 +03:00
|
|
|
(defmodule Array
|
|
|
|
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc reduce "Reduce an array, using the function f.")
|
2017-10-17 09:57:36 +03:00
|
|
|
(defn reduce [f x xs]
|
|
|
|
(let [total x]
|
|
|
|
(do
|
2018-05-20 10:57:51 +03:00
|
|
|
(for [i 0 (length xs)]
|
2018-11-14 16:09:43 +03:00
|
|
|
(set! total (~f total (nth xs i))))
|
2017-10-17 09:57:36 +03:00
|
|
|
total)))
|
2017-10-26 18:37:44 +03:00
|
|
|
|
2018-11-08 20:01:31 +03:00
|
|
|
(doc empty? "Checks whether the array is empty.")
|
|
|
|
(defn empty? [a]
|
|
|
|
(= (Array.length a) 0))
|
|
|
|
|
2018-11-08 21:13:02 +03:00
|
|
|
(doc any? "Checks whether any of the elements in `a` match the function `f`.")
|
|
|
|
(defn any? [f a]
|
2018-11-08 21:31:54 +03:00
|
|
|
(let-do [res false]
|
|
|
|
(for [i 0 (length a)]
|
2018-11-14 16:09:43 +03:00
|
|
|
(when (~f (nth a i))
|
2018-11-08 21:31:54 +03:00
|
|
|
(do
|
|
|
|
(set! res true)
|
|
|
|
(break))))
|
|
|
|
res))
|
2018-11-08 21:13:02 +03:00
|
|
|
|
|
|
|
(doc all? "Checks whether all of the elements in `a` match the function `f`.")
|
|
|
|
(defn all? [f a]
|
2018-11-08 21:31:54 +03:00
|
|
|
(let-do [res true]
|
|
|
|
(for [i 0 (length a)]
|
2018-11-14 16:09:43 +03:00
|
|
|
(when (not (~f (nth a i)))
|
2018-11-08 21:31:54 +03:00
|
|
|
(do
|
|
|
|
(set! res false)
|
|
|
|
(break))))
|
|
|
|
res))
|
2018-11-08 21:13:02 +03:00
|
|
|
|
|
|
|
(doc find "Finds an element in `a` that matches the function `f`.")
|
|
|
|
(defn find [f a]
|
|
|
|
(let-do [res (zero)]
|
|
|
|
(for [i 0 (length a)]
|
2018-11-14 16:09:43 +03:00
|
|
|
(when (~f (nth a i))
|
2018-11-08 21:13:02 +03:00
|
|
|
(do
|
|
|
|
(set! res @(nth a i))
|
|
|
|
(break))))
|
|
|
|
res))
|
|
|
|
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc first "Take the first element of an array.")
|
2017-11-29 17:28:21 +03:00
|
|
|
(defn first [a]
|
|
|
|
@(Array.nth a 0))
|
|
|
|
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc last "Take the last element of an array.")
|
2017-11-29 17:28:21 +03:00
|
|
|
(defn last [a]
|
2018-05-20 10:57:51 +03:00
|
|
|
@(Array.nth a (Int.dec (Array.length a))))
|
2017-12-04 09:21:35 +03:00
|
|
|
|
2018-05-07 22:51:46 +03:00
|
|
|
(doc = "Compare two arrays.")
|
2017-12-19 14:46:46 +03:00
|
|
|
(defn = [a b]
|
2018-05-20 10:57:51 +03:00
|
|
|
(if (/= (length a) (length b))
|
2017-12-19 14:46:46 +03:00
|
|
|
false
|
|
|
|
(let-do [eq true]
|
2018-05-20 10:57:51 +03:00
|
|
|
(for [i 0 (length a)]
|
2017-12-19 14:46:46 +03:00
|
|
|
(when (/= @(nth a i) @(nth b i))
|
|
|
|
(do
|
2018-02-02 09:19:10 +03:00
|
|
|
(set! eq false)
|
2017-12-19 14:46:46 +03:00
|
|
|
(break))))
|
|
|
|
eq)))
|
|
|
|
|
2018-06-26 11:11:47 +03:00
|
|
|
(defn /= [a b]
|
2018-07-17 16:49:15 +03:00
|
|
|
(not (= (the (Ref (Array a)) a) b)))
|
2018-06-26 11:11:47 +03:00
|
|
|
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc maximum "Get the maximum in an array (elements must support <).")
|
2018-01-29 09:14:41 +03:00
|
|
|
(defn maximum [xs]
|
2017-12-04 09:21:35 +03:00
|
|
|
(let [result (first xs)
|
2018-05-20 10:57:51 +03:00
|
|
|
n (length xs)]
|
2017-12-04 09:21:35 +03:00
|
|
|
(do
|
2018-01-29 12:55:45 +03:00
|
|
|
(for [i 1 n]
|
2017-12-04 09:21:35 +03:00
|
|
|
(let [x @(nth xs i)]
|
2018-01-29 09:14:41 +03:00
|
|
|
(if (< result x)
|
2018-02-02 09:19:10 +03:00
|
|
|
(set! result x)
|
2017-12-04 09:21:35 +03:00
|
|
|
())))
|
|
|
|
result)))
|
|
|
|
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc minimum "Get the maximum in an array (elements must support >).")
|
2018-01-29 09:14:41 +03:00
|
|
|
(defn minimum [xs]
|
2017-12-04 09:21:35 +03:00
|
|
|
(let [result (first xs)
|
2018-05-20 10:57:51 +03:00
|
|
|
n (length xs)]
|
2017-12-04 09:21:35 +03:00
|
|
|
(do
|
2018-01-29 12:55:45 +03:00
|
|
|
(for [i 1 n]
|
2017-12-04 09:21:35 +03:00
|
|
|
(let [x @(nth xs i)]
|
2018-01-29 09:14:41 +03:00
|
|
|
(if (> result x)
|
2018-02-02 09:19:10 +03:00
|
|
|
(set! result x)
|
2017-12-04 09:21:35 +03:00
|
|
|
())))
|
|
|
|
result)))
|
|
|
|
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc minimum "Sum an array (elements must support + and zero).")
|
2017-12-04 09:21:35 +03:00
|
|
|
(defn sum [xs]
|
2018-11-14 16:09:43 +03:00
|
|
|
(Array.reduce &(fn [x y] (+ x @y)) (zero) xs))
|
2017-12-08 17:12:50 +03:00
|
|
|
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc subarray "Get subarray from start-index to end-index.")
|
2017-12-19 14:46:46 +03:00
|
|
|
(defn subarray [xs start-index end-index]
|
2017-12-08 17:12:50 +03:00
|
|
|
(let [result []]
|
|
|
|
(do
|
2017-12-19 14:46:46 +03:00
|
|
|
(for [i start-index end-index]
|
2018-03-11 16:30:38 +03:00
|
|
|
(set! result (push-back result @(nth xs i))))
|
2017-12-08 17:12:50 +03:00
|
|
|
result)))
|
2017-12-18 18:53:46 +03:00
|
|
|
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc prefix-array "Get prefix-array to end-index.")
|
2017-12-19 14:46:46 +03:00
|
|
|
(defn prefix-array [xs end-index]
|
|
|
|
(subarray xs 0 end-index))
|
|
|
|
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc suffix-array "Get subarray from start-index.")
|
2017-12-19 14:46:46 +03:00
|
|
|
(defn suffix-array [xs start-index]
|
2018-05-20 10:57:51 +03:00
|
|
|
(subarray xs start-index (length xs)))
|
2017-12-19 14:46:46 +03:00
|
|
|
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc reverse "Reverse an array.")
|
2017-12-18 18:53:46 +03:00
|
|
|
(defn reverse [a]
|
|
|
|
(let-do [i 0
|
2018-05-20 10:57:51 +03:00
|
|
|
j (Int.dec (length &a))]
|
2017-12-18 18:53:46 +03:00
|
|
|
(while (Int.< i j)
|
|
|
|
(let-do [tmp @(nth &a i)]
|
|
|
|
(aset! &a i @(nth &a j))
|
2018-02-02 09:19:10 +03:00
|
|
|
(set! i (Int.inc i))
|
2017-12-18 18:53:46 +03:00
|
|
|
(aset! &a j tmp)
|
2018-02-02 09:19:10 +03:00
|
|
|
(set! j (Int.dec j))))
|
2017-12-18 18:53:46 +03:00
|
|
|
a))
|
2018-01-02 16:39:24 +03:00
|
|
|
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc index-of "Get the index of element e in an array.")
|
2018-01-02 16:39:24 +03:00
|
|
|
(defn index-of [a e]
|
|
|
|
(let-do [idx -1]
|
2018-05-20 10:57:51 +03:00
|
|
|
(for [i 0 (length a)]
|
2018-03-12 14:04:23 +03:00
|
|
|
(when (= (nth a i) &e)
|
2018-01-02 16:39:24 +03:00
|
|
|
(do
|
2018-02-02 09:19:10 +03:00
|
|
|
(set! idx i)
|
2018-01-02 16:39:24 +03:00
|
|
|
(break))))
|
|
|
|
idx))
|
|
|
|
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc element-count "Count occurrences of element e in an array.")
|
2018-01-02 16:39:24 +03:00
|
|
|
(defn element-count [a e]
|
|
|
|
(let-do [c 0]
|
2018-05-20 10:57:51 +03:00
|
|
|
(for [i 0 (length a)]
|
2018-03-12 14:11:33 +03:00
|
|
|
(when (= e (nth a i)) (set! c (Int.inc c))))
|
2018-01-02 16:39:24 +03:00
|
|
|
c))
|
2018-01-02 20:13:52 +03:00
|
|
|
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc aupdate "Transmute the element at index i of array a using function f.")
|
2018-01-02 20:13:52 +03:00
|
|
|
(defn aupdate [a i f]
|
2018-11-14 16:09:43 +03:00
|
|
|
(let [new-value (~f (nth &a i))]
|
2018-03-11 15:28:08 +03:00
|
|
|
(aset a i new-value)))
|
2018-01-02 20:13:52 +03:00
|
|
|
|
2018-06-23 06:28:24 +03:00
|
|
|
(doc aupdate! "Transmute the element at index i of array a using function f in place.")
|
2018-01-02 20:13:52 +03:00
|
|
|
(defn aupdate! [a i f]
|
2018-11-14 16:09:43 +03:00
|
|
|
(aset! a i (~f (nth a i))))
|
2018-01-02 20:13:52 +03:00
|
|
|
|
2018-06-23 06:28:24 +03:00
|
|
|
(doc swap "Swap indices i and j of array a.")
|
2018-01-02 20:13:52 +03:00
|
|
|
(defn swap [a i j]
|
2018-03-11 12:38:24 +03:00
|
|
|
(let [x @(nth &a i)
|
|
|
|
y @(nth &a j)]
|
|
|
|
(aset (aset a i y) j x)))
|
2018-01-02 20:13:52 +03:00
|
|
|
|
2018-06-23 06:28:24 +03:00
|
|
|
(doc swap! "Swap indices i and j of array a in place.")
|
2018-01-02 20:13:52 +03:00
|
|
|
(defn swap! [a i j]
|
|
|
|
(let-do [x @(nth a i)
|
|
|
|
y @(nth a j)]
|
|
|
|
(aset! a i y)
|
|
|
|
(aset! a j x)))
|
|
|
|
|
2018-01-09 14:36:12 +03:00
|
|
|
; cannot use for, because we want also be able to go downwards
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc range "Create an array from start to end with step between them (the elements must support <, <=, and >=).")
|
2018-01-09 14:36:12 +03:00
|
|
|
(defn range [start end step]
|
2018-01-24 16:07:43 +03:00
|
|
|
(let-do [x (allocate (Int.inc (Int.abs (/ (- end start) step))))
|
2018-01-10 13:42:19 +03:00
|
|
|
e start
|
2018-01-24 16:07:43 +03:00
|
|
|
i 0
|
2018-01-10 16:24:32 +03:00
|
|
|
op (if (< start end) <= >=)]
|
|
|
|
(while (op e end)
|
2018-01-09 14:36:12 +03:00
|
|
|
(do
|
2018-01-24 16:07:43 +03:00
|
|
|
(aset! &x i e)
|
2018-02-02 09:19:10 +03:00
|
|
|
(set! i (Int.inc i))
|
|
|
|
(set! e (+ e step))))
|
2018-01-09 14:36:12 +03:00
|
|
|
x))
|
|
|
|
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc repeat "Repeat function f n times and store the results in an array.")
|
2018-01-24 16:07:43 +03:00
|
|
|
(defn repeat [n f]
|
|
|
|
(let-do [a (allocate n)]
|
2018-11-14 16:09:43 +03:00
|
|
|
(for [i 0 n] (aset-uninitialized! &a i (~f)))
|
2018-01-24 16:07:43 +03:00
|
|
|
a))
|
|
|
|
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc repeat-indexed "Repeat function f n times and store the results in an array (will be supplied with the index).")
|
2018-01-24 16:07:43 +03:00
|
|
|
(defn repeat-indexed [n f]
|
|
|
|
(let-do [a (allocate n)]
|
2018-03-12 16:37:53 +03:00
|
|
|
(for [i 0 n] (aset-uninitialized! &a i (f i)))
|
2018-01-24 16:07:43 +03:00
|
|
|
a))
|
|
|
|
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc replicate "Repeat element e n times and store the results in an array.")
|
2018-01-24 16:07:43 +03:00
|
|
|
(defn replicate [n e]
|
|
|
|
(let-do [a (allocate n)]
|
2018-03-12 16:37:53 +03:00
|
|
|
(for [i 0 n] (aset-uninitialized! &a i @e))
|
2018-01-24 16:07:43 +03:00
|
|
|
a))
|
2018-01-24 16:41:50 +03:00
|
|
|
|
2018-03-29 12:36:42 +03:00
|
|
|
(doc copy-map "Map over array a using function f (copies the array).")
|
2018-01-24 16:41:50 +03:00
|
|
|
(defn copy-map [f a]
|
2018-05-20 10:57:51 +03:00
|
|
|
(let-do [na (allocate (length a))]
|
|
|
|
(for [i 0 (length a)]
|
2018-11-14 16:09:43 +03:00
|
|
|
(aset-uninitialized! &na i (~f (nth a i))))
|
2018-01-24 16:41:50 +03:00
|
|
|
na))
|
2018-04-23 13:20:00 +03:00
|
|
|
|
2018-06-01 12:18:03 +03:00
|
|
|
(doc zip "Map over two arrays using a function that takes two arguments. Produces a new array with the length of the shorter input.")
|
|
|
|
(defn zip [f a b]
|
2018-06-01 12:00:50 +03:00
|
|
|
(let-do [l (Int.min (length a) (length b))
|
|
|
|
na (allocate l)]
|
|
|
|
(for [i 0 l]
|
2018-11-14 16:09:43 +03:00
|
|
|
(aset-uninitialized! &na i (~f (nth a i) (nth b i))))
|
2018-06-01 12:00:50 +03:00
|
|
|
na))
|
|
|
|
|
2018-05-20 10:57:51 +03:00
|
|
|
(doc sum-length "Returns the sum of lengths from an Array of Arrays.")
|
|
|
|
(defn sum-length [xs]
|
2018-05-20 10:20:57 +03:00
|
|
|
(let-do [sum 0
|
2018-05-20 10:57:51 +03:00
|
|
|
lxs (Array.length xs)]
|
2018-05-20 10:20:57 +03:00
|
|
|
(for [i 0 lxs]
|
2018-05-20 10:57:51 +03:00
|
|
|
(set! sum (+ sum (Array.length (Array.nth xs i)))))
|
2018-05-20 10:20:57 +03:00
|
|
|
sum))
|
|
|
|
|
2018-08-06 21:47:09 +03:00
|
|
|
(doc zero "Returns the empty array.")
|
|
|
|
(defn zero [] [])
|
|
|
|
|
2018-05-20 10:20:57 +03:00
|
|
|
(doc concat "Returns a new Array which is the concatenation of the provided `xs`.")
|
2018-04-23 13:20:00 +03:00
|
|
|
(defn concat [xs]
|
2018-05-20 10:20:57 +03:00
|
|
|
;; This is using a StringBuilder pattern to only perform one allocation and
|
|
|
|
;; to only copy each of the incoming Array(s) once.
|
2018-05-20 10:57:51 +03:00
|
|
|
;; This currently performs wasted Array.length calls, as we call it for each
|
|
|
|
;; Array once here and once in sum-length.
|
2018-05-20 10:20:57 +03:00
|
|
|
(let-do [j 0
|
2018-05-20 10:57:51 +03:00
|
|
|
lxs (Array.length xs)
|
|
|
|
result (Array.allocate (sum-length xs))]
|
2018-05-20 10:20:57 +03:00
|
|
|
(for [i 0 lxs]
|
|
|
|
(let-do [arr (Array.nth xs i)
|
2018-05-20 10:57:51 +03:00
|
|
|
len (Array.length arr)]
|
2018-05-20 10:20:57 +03:00
|
|
|
(for [k 0 len]
|
|
|
|
(aset-uninitialized! &result (+ j k) @(Array.nth arr k)))
|
|
|
|
(set! j (+ j len))))
|
2018-04-23 13:20:00 +03:00
|
|
|
result))
|
2018-06-01 12:00:50 +03:00
|
|
|
|
2018-06-01 12:18:03 +03:00
|
|
|
(doc enumerated "Create a new array of Pair:s where the first position is the index and the second position is the element from the original array.")
|
2018-06-01 12:00:50 +03:00
|
|
|
(defn enumerated [xs]
|
2018-11-14 16:09:43 +03:00
|
|
|
(zip &Pair.init-from-refs
|
2018-06-01 12:18:03 +03:00
|
|
|
&(range 0 (length xs) 1) ;; Inefficient, creates a temporary array.
|
|
|
|
xs))
|
2017-10-26 18:37:44 +03:00
|
|
|
)
|