Ways to quickly update an element of a matrix in Incanter, Clojure? - clojure

Suppose I have a 3x3 matrix
(def myMatrix (matrix (range 9) 3))
; A 3x3 matrix
; -------------
; 0.00e+00 1.00e+00 2.00e+00
; 3.00e+00 4.00e+00 5.00e+00
; 6.00e+00 7.00e+00 8.00e+00
I can use $ to get an element, say 2nd row 1st column
($ 1 0 myMatrix) ; --> 3
Is there any API method to quickly update an element and then return a matrix? e.g.
(update-matrix-by-element 2 1 myMatrix 4)
; A 3x3 matrix
; -------------
; 0.00e+00 1.00e+00 2.00e+00
; 4.00e+00 4.00e+00 5.00e+00
; 6.00e+00 7.00e+00 8.00e+00
The closest API methods I can find are bind-rows and bind-columns, and my current version of function using these two methods is
;note i j starts from 1 rather than 0
(defn update-matrix-by-element [i j myMatrix value]
(if (or (> i (count (trans myMatrix))) (> j (count myMatrix)) (< i 1) (< j 1) (not (integer? i)) (not (integer? j)))
myMatrix
(let [n (count myMatrix)
m (count (trans myMatrix))
rangeFn #(if (== %1 %2) %1 (range %1 %2 ))
m1 (if (== (dec i) 0) []
($ (rangeFn 0 (dec i)) :all myMatrix))
m2 (if (== i m) []
($ (rangeFn i m) :all myMatrix))
matrixFn #(if (matrix? % ) % [ %])
newRow (if (== (dec j) 0)
(bind-columns [value] (matrixFn ($ (dec i) (rangeFn j n ) myMatrix)))
(if (== j n )
(bind-columns (matrixFn ($ (dec i) (rangeFn 0 (dec j) ) myMatrix)) [value] )
(bind-columns (matrixFn ($ (dec i) (rangeFn 0 (dec j) ) myMatrix)) [value] (matrixFn ($ (dec i) (rangeFn j n ) myMatrix))))
)
]
; (prn " m1 " m1 ) (prn " m2 " m2 ) (prn " newrow " newRow)
(bind-rows m1 newRow m2))))

If you mean "quickly" in the sense of performance, then you may probably to look at core.matrix which is designed to support fast mutable matrix operations.
Example using the vectorz-clj implementation for core.matrix:
(def M (matrix [[1 2] [3 4]]))
=> #<Matrix22 [[1.0,2.0][3.0,4.0]]>
(mset! M 0 0 10)
=> #<Matrix22 [[10.0,2.0][3.0,4.0]]>
(time (dotimes [i 1000000] (mset! M 0 0 i)))
"Elapsed time: 28.895842 msecs" ;; i.e. < 30ns per mset! operation
This will be much faster than anything which requires construction of a new mutable matrix, especially as the matrices get bigger / have higher dimensionality.
I'm working on making core.matrix integrate neatly with Incanter, so you should be able to use core.matrix matrices transparently within Incanter before too long.

Related

Convert pseudo-code with nested for-loops to Clojure

I want to implement this psuedo code in Clojure:
function(n)
B[0] <-- 1
for m <-- 1 to n do
B[m] <-- 0
for k <-- 0 to m - 1 do
B[m] <-- B[m] − binom(m+1, k) * B[k]
B[m] <-- B[m]/(m+1)
return B[n]
My first thought was to do something like this:
(defn foo [n]
(if (= n 0)
(int 1)
(for [k (range 0 (- n 1))]
(* (binom (+ n 1) k)
(foo k)))))
but now I'm stuck and I don't know how to continue. The nested loops confuse me a lot when I try to translate them to Clojure.
I'd really appreciate some help on how to write this code in Clojure, I feel a bit lost.
Thanks in advance!
Some algorithms are naturally imperative in nature. Don't be afraid to write imperative code if that is the easiest solution, rather than trying to "force fit" the algorithm into a functional style.
This algorithm could easily use a mutable atom to store the B array:
(defn factorial [x]
(reduce * (range 2 (inc x))))
(defn binom [n k]
(/ (factorial n)
(factorial k) (factorial (- n k))))
(defn bernoulli [n]
(let [B (atom (vec (repeat n 0)))] ; allocate B[0]..B[n-1] = zeros
(swap! B assoc 0 1) ; B[0] = 1
(doseq [m (range 1 (inc n))] ; 1..n
(swap! B assoc m 0) ; B[m] = 0
(doseq [k (range m)] ; 0..(m-1)
(swap! B #(assoc % m ; B[m] = ...
(-
(get % m) ; B[m]
(*
(binom (inc m) k)
(get % k)))))) ; B[k]
(swap! B update m ; B[m] = B[m] ...
#(/ % (inc m))))
(get #B n)))
(dotest
(dotimes [i 10]
(spyx [i (bernoulli i)])))
with result
[i (bernoulli i)] => [0 1]
[i (bernoulli i)] => [1 -1/2]
[i (bernoulli i)] => [2 1/6]
[i (bernoulli i)] => [3 0N]
[i (bernoulli i)] => [4 -1/30]
[i (bernoulli i)] => [5 0N]
[i (bernoulli i)] => [6 1/42]
[i (bernoulli i)] => [7 0N]
[i (bernoulli i)] => [8 -1/30]
[i (bernoulli i)] => [9 0N]
You could also use with-local-vars for some algorithms, or even drop down into a (mutable) Java array. You can see an example of that in this mutable Java matrix example
The given pseudocode computes the nth Bernoulli number. It uses all the previous Bernoulli numbers to compute the result. Much like the factorial function, this lends itself to a recursive algorithm which may be implemented with memoize to avoid re-computation of earlier numbers:
(def factorial
"Returns n!."
(memoize (fn [n]
(if (< 1 n)
(* n (factorial (dec n)))
1N))))
(def bernoulli
"Returns the nth Bernoulli number."
(memoize (fn [n]
(if (zero? n)
1
(let [n! (factorial n)
term #(/ (* n! (bernoulli %))
(factorial %)
(factorial (- n % -1)))
terms (map term (range n))]
(reduce - 0 terms))))))
(map bernoulli (range 9)) ; => (1 -1/2 1/6 0N -1/30 0N 1/42 0N -1/30)
The pseudo code uses plenty of in-place updates which makes it a bit hard to read. But essentially, the code computes a list of numbers where every number is computed from the previous numbers in the list. And then we pick one of the numbers in the list.
I would implement this algorithm like
(defn compute-next-B [B]
(let [m (count B)
m+1 (inc m)
terms (map-indexed (fn [k Bk] (- (* Bk (binom m+1 k)))) B)]
(conj B (/ (apply + terms) m+1))))
(defn foo [n]
(->> [1]
(iterate compute-next-B)
(drop n)
first
last))
The outer loop from the pseudo code is the lazy sequence produced by (iterate compute-next-B ...). The inner loop from the pseudo code is the iteration inside (apply + terms) on the lazy sequence terms.

How to break a for loop in Clojure?

I have the following function:
(defn next-transformation
[arr]
(let [
arr-len (count arr)
i-range (range 0 arr-len)
j-range (range 0 arr-len)
indexes (for [i i-range
j j-range]
(let [
xi (nth arr i)
xj (nth arr j)
]
(if (> xi xj)
[i j]
nil
)
)
)
non-nil-indexes (filter
(fn [elem]
(not (= elem nil))
)
indexes
)
]
(if (not (empty? non-nil-indexes))
(first non-nil-indexes)
nil
)
)
)
It returns the first element of an array of tuples [i j] which describe elments of the array arr for which arr[i] > arr[j] is true.
The for loop in the fragment below runs through every pair of i and j:
indexes (for [i i-range
j j-range]
(let [
xi (nth arr i)
xj (nth arr j)
]
(if (> xi xj)
[i j] ;; I want the loop to stop here
nil
)
)
)
How can I modify this for loop so that it stops once it finds the first relevant tuple (i. e. the loop should stop at the place marked with ;; I want the loop to stop here comment)?
Here is the equivalent code in Java:
private Integer[] next-transformation(final Integer[] arr) {
for (int i=0; i < arr.length; i++) {
for (int j=0; j < arr.length; j++) {
if (arr[i] > arr[j]) {
return new Integer[] {i, j};
}
}
}
}
Update 1:
As recommended by #CharlesDuffy, I replaced for with loop/recur:
(defn next-transformation
[arr]
(loop [i 0
j 0]
(let [
arr-len (count arr)
]
(if (and (< i arr-len)
(< j arr-len))
(let [
xi (nth arr i)
xj (nth arr j)
j-plus-1 (+ j 1)
i-plus-1 (+ i 1)
new-i (if (< j-plus-1 arr-len)
i
(+ i 1))
new-j (if (< j-plus-1 arr-len)
(+ j 1)
0)
]
(if (> xi xj)
;; We found it
[i j]
;; We haven't found it, recur
(recur new-i new-j)
)
)
nil ; We are at the end of the loop
) ; if
)
) ; loop
) ; defn
In the for list comprehension, use :when to filter for the tuples of interest, and use first to return just the first one:
(defn next-transformation [arr]
(first (for [i (range (count arr))
j (range (count arr))
:when (> (nth arr i) (nth arr j))]
[i j])))

Beginner's clojure attempt to hackkerrank problem timing out

I'm attempting the following problem on hackerrank:
https://www.hackerrank.com/challenges/counting-valleys
but unfortunately my following clojure code is timing out on many test cases, and I don't know what makes it so inefficient. Please be lenient. I only have in total 2 hours of total clojure experience.
(require '[clojure.string :as str])
; Complete the countingValleys function below.
(defn countingValleys [n s]
(do
(def running 0)
(defn counter [elem]
(do
(cond
(= elem "D") (def running (+ running 1))
(= elem "U")(def running (- running 1))
)
running
)
)
(def valley-num 0)
(defn valley-count [a b]
(do
(if (and (= a "U") (= b 0))
(def valley-num (+ valley-num 1)))
)
)
(def heights (for [elem s] (counter elem)))
(doseq [[i j] (map vector s heights)]
(valley-count i j))
valley-num
)
)
(def fptr (get (System/getenv) "OUTPUT_PATH"))
(def n (Integer/parseInt (clojure.string/trim (read-line))))
(def s (read-line))
(def result (countingValleys n (str/split s #"")))
(spit fptr (str result "\n") :append true)
Dead easy python implementation of the same logic that took 5 minutes and passes all test cases:
def countingValleys(n, s):
list = []
for i in range(len(s)):
d = 0
if s[i] == "D":
d = 1
elif s[i] == "U":
d = -1
if len(list) == 0:
list.append(d)
else:
list.append(list[-1] + d)
num = 0
for i in range(len(s)):
if s[i] == "U" and list[i] == 0:
num += 1
return num
So I figured it out. The inefficiency was in this line:
(doseq [[i j] (map vector s heights)]
(valley-count i j))
Which can be replaced with:
(doall (map valley-count s heights))
and then all tests pass.
The slowness of your code is the least of its problems. The tools you ought to be employing are
pure functions,
the sequence library,
and, for speed, the prospect of transducers.
I like your underlying algorithm: count the cases where an up movement takes you to sea level.
We can express it idiomatically thus:
(defn countingValleys [n s]
(let [counter {\D 1, \U -1}
heights (reductions + (map counter s))
s-heights (map vector s heights)
valley-num (count (filter #{[\U 0]} s-heights))]
valley-num))
... or, using the ->> threading macro ...
(defn countingValleys [_ s]
(->> s
(map {\D 1, \U -1})
(reductions +)
(map vector s)
(filter #{[\U 0]})
(count)))
These are clearer and faster than yours.
It seems that you and HackerRank are actually using ClojureScript. Your use of "U" as an element of a string won't work in Clojure proper: you have to use the character \U.
Those of us who are JavaScript(Node JS) developers, my solution here works perfectly
// Complete the countingValleys function below.
function countingValleys(n, s) {
const min = 2;
const max = 1000000;
let valleys = 0;
let isInValley;
s = (typeof s === 'string') ? s.split('') : s;
if (s.length >= min && s.length <= max &&
n === parseInt(n, 0) &&
n >= min &&
n <= max &&
n === s.length) {
s.map(steps => ((steps === "U") ? 1 : -1))
.reduce((prev, next) => {
if (prev < 0 && !isInValley) {
isInValley = true;
}
if ((prev + next) === 0 && isInValley) {
valleys++;
isInValley = false;
}
return prev + next;
});
}
return valleys;
}

How do I translate a complicated recurrence from clojure to maxima?

I think this little program:
(defn average [lst] (/ (reduce + lst) (count lst)))
(defn sqsum [lst] (reduce + (map #(* % %) lst)))
(defn tet [row col]
(cond (= [row col] [0 0]) 0
(= [row col] [1 0]) 1
(< row (inc col)) 0
(> row (inc col)) (average (for [i (range row)] (tet i col)))
(= row (inc col)) (Math/sqrt (- 1 (sqsum (for [i (range col)] (tet row i)))))))
gives me the coordinates of the vertices of generalised tetrahedra / euclidean simplices in various dimensions.
Unfortunately clojure will express things like sqrt(3/4) in floating point, whereas I'd like the answers in symbolic form.
Maxima would be ideal for this sort of thing, but I don't know how to express this relation in maxima.
Alternatively, solutions involving adding symbolic square roots to clojure would also be nice.
In Maxima, a memoizing function is defined by f[x, y] := ..., that is, with square brackets instead of parentheses for the arguments.
From what I can tell, this is a translation of the Clojure function:
average (lst) := apply ("+", lst) / length (lst);
sqsum (lst) := apply ("+", map (lambda ([x], x^2), lst));
tet [row, col] :=
if row < col + 1 then 0
else if row > col + 1 then average (makelist (tet [i, col], i, 0, row - 1))
else if row = col + 1 then sqrt (1 - sqsum (makelist (tet [row, i], i, 0, col - 1)));
tet [0, 0] : 0;
tet [1, 0] : 1;
E.g.:
radcan (tet[4, 3]);
=> sqrt(5)/2^(3/2)
radcan (tet[7, 6]);
=> 2/sqrt(7)
First one agrees with a[4, 3] above. Dunno about the second.
This does the business
a[0,0]:0;
a[1,0]:1;
for row:2 while row<=15 do (
(col:(row-1)),
for r:0 while r<=col do (a[r,col]:0),
for c:0 while c<col do (a[row,c]:(sum(a[i,c],i,0,row-1))/row),
a[row,col]:radcan(sqrt(1-sum(a[row,c]^2,c,0,col-1))),
disp(a[row,col]^2));
But is there anyway to express it as the original recursion and memoize it so it runs in finite time?
I've done the first few 'by hand' in maxima, like this, if anyone needs inspiration.
(This is the 2d iteration which is equivalent to the above recursion (once memoized))
So I guess my question now could be 'how do I express this as a for loop in maxima'
one-simplex
a[0,0]:0;
a[1,0]:1;
two-simplex (equilateral triangle)
a[0,1]:0;
a[1,1]:0;
a[2,0]:(a[0,0]+a[1,0])/2;
a[2,1]:sqrt(1-a[2,0]^2);
three-simplex (tetrahedron)
a[0,2]:0;
a[1,2]:0;
a[2,2]:0;
a[3,0]:(a[0,0]+a[1,0]+a[2,0])/3;
a[3,1]:(a[0,1]+a[1,1]+a[2,1])/3;
a[3,2]:sqrt(1-a[3,0]^2-a[3,1]^2);
four-simplex (tetrahedron)
col:3;
a[0,col]:0;
a[1,col]:0;
a[2,col]:0;
a[3,col]:0;
col:0;
a[4,col]:(a[0,col]+a[1,col]+a[2,col]+a[3,col])/4;
col:1;
a[4,col]:(a[0,col]+a[1,col]+a[2,col]+a[3,col])/4;
col:2;
a[4,col]:(a[0,col]+a[1,col]+a[2,col]+a[3,col])/4;
a[4,3]:sqrt(1-a[4,0]^2-a[4,1]^2-a[4,2]^2);
radcan(%);

Idiomatic way to use for, while still maintaining high performance

I have a map that is sorted by its keys which contains data like this:
(def h {50 Text1
70 Text2
372 Text1
391 Text2
759 Text1
778 Text2
})
The map is sorted by Keys. The key (the number) can be interpreted as the position where the corresponding value was found in a large block of text. In the above example, "Text1" was found at position 50 in the text.
Now, I want to find all Texts that were found within k positions of each other. I define a function a like this:
(defn nearest [m k]
(for [m1 (keys m) m2 (keys m)
:when (and (> m2 m1) (not= (m m1) (m m2)) (< (- m2 m1) k))]
[m1 (get m m1) m2 (get m m2)]))
(nearest h 50)
; [[50 "Text1" 70 "Text2"] [372 "Text1" 391 "Text2"] [759 "Text1" 778 "Text2"]]
This works, but is too slow when the map m has 100s of thousands of elements. Because the for loop actually looks at all pairs of elements in the map. Since the map is sorted, for each element in the map, it is not necessary to check further elements, once the next element is already beyond k characters. I was able to write a version using loop and recur. But it is kind of unreadable. Is there a more natural way to do this using for? I am assuming for (:while ) should do the trick, but was not able to find a way.
(defn nearest-quick [m k]
(let [m1 (keys m) m2 (keys m)]
(loop [inp m res [] i (first m1) m1 (rest m1) j (first m2) m2 (rest m2)]
(cond
(nil? i) res
(nil? j)(recur inp res (first m1) (rest m1) j m2)
(= i j) (recur inp res i m1 (first m2) (rest m2))
(< j i) (recur inp res i m1 (first m2) (rest m2))
(= (inp i) (inp j)) (recur inp res i m1 (first m2) (rest m2))
(< (- j i) k) (recur inp (conj res [i (inp i) j (inp j)]) i m1 (first m2) (rest m2))
(>= (- j i) k) (recur inp res (first m1) (rest m1) (first (rest m1)) (rest (rest m1)))))))
Note: with a map with 42K elements, the first version takes 90 mins and the second version takes 3 mins.
One could probably exploit subseq when the map is a sorted-map.
(defn nearest
[m n]
(for [[k v] m
[nk nv] (subseq m < k < (+ k n))
:when (not= v nv)]
[k v nk nv]))
Code not benchmarked.
Clojure's for also has a :while modifier, so you can stop the iteration with a condition.
From whatever I have understood from you example:
(def h (sorted-map 50 "Text1"
70 "Text2"
372 "Text1"
391 "Text2"
759 "Text1"
778 "Text2"))
(->> (map #(-> [%1 %2]) h (rest h))
(filter (fn [[[a b] [x y]]] (< (- x a) 50)))
(map flatten))