I'm working on a Clojure project that takes as an input an array a
, and finds the minimum in the range [i,j]
for each i
, j
, in O(n)
preproccessing, and O(1)
for each query.
(preproccessing takes O(n*log(n))
, but by using concurrency (pmap
) and dividing the array to n/log n
arrays we can solve this problem in O(n)
)
So, I choce to represent the array as a vector, and the matrix as vector of vectors.
This is one of the functions in C#:
void build_RMQ_log(int[] a)
{
ST = new int[2 * a.Length][];
for (int i = 0; i < 2 * a.Length; i++)
ST[i] = new int[(int)Math.Log(a.Length, 2)];
for (int i = 0; i < a.Length; i++)
{
ST[i][0] = i;
ST[i + a.Length - 1][0]=0;
}
for (int j = 1; j < (int)Math.Log(a.Length, 2); j++)
{
for (int i = 0; i < a.Length; i++)
{
if (a[ST[i][j - 1]] <= a[ST[i + (int)Math.Pow(2, j - 1)][j - 1]])
ST[i][j] = ST[i][j - 1];
else
ST[i][j] = ST[i + (int)Math.Pow(2, j - 1)][j - 1];
}
}
}
i
And this is how I wrote it in Clojure:
;build_RMQ_log(int[] a)
(defn check [row1 row2 arr j]
(let [x1 (nth arr (nth row1 j))
x2 (nth arr (nth row2 (- j 1)))
x3 (nth arr (nth row1 (- j 1)))]
(if (<= x1 x2)
(assoc row1 j (nth row1 (- j 1)))
(assoc row1 j (nth row2 (- j 1))))))
(defn apply_fn [ST a row r]
(let [len (count a)
cnt (/ len (log_ len 2))]
(loop[ii 0 r 0]
(if (= ii (- cnt 1))
ST
(recur (inc ii) (check row (nth ST (+ r (Math/pow 2 (- ii 1)))) a ii))))))
(defn build_RMQ_log [a]
(let [len (count a)
ST (diag_n_m len (log_ len 2))
r 0]
(pmap (fn [row] (apply_fn (ST a row r))) ST )))
First of all, when i try to run it, it shows me this error:
#<IllegalArgumentException java.lang.IllegalArgumentException: Wrong number of args (3) passed to: PersistentVector>
besides, The code that I wrote doesn't do what I want, because I dont know how can I change the value of r
(that represents the row number) if apply_fn
works in parallel. I.e. like it changes in c#:
for (int i = 0; i < a.Length; i++)
(r
is like i
in the for
-loop in c#)
Thanks in Advance.
If I undestand you correctly, you want to pass an incrementing r
to each call of apply_fn
. You could try this:
(defn build_RMQ_log [a]
(let [len (count a)
ST (diag_n_m len (log_ len 2))
rs (range)]
(pmap (fn [row r] (apply_fn (ST a row r))) ST rs)))
That is, you're passing two collections to pmap
where the second collection is an infinite collection of increasing integers (i.e. [0, 1, 2, 3, ...]
).