I am a Clojure beginner and I cannot decode the meaning of the error or understand why it is happening in my small program to find the smallest number in a sequence.
(defn find-min
[nums]
(loop [smallest 1000000 i 0]
(if (= (count nums) i)
smallest)
(if (< (nums i) smallest)
(recur (nums i) (inc i))
(recur smallest (inc i)))))
(find-min [3 4 0 2])
IndexOutOfBoundsException clojure.lang.PersistentVector.arrayFor (PersistentVector.java:158)
Now I do understand that there is an Index out of bound error but the first if function takes care that the function returns so why is it happening?
Your two if are on the same level, so both of them will be executed subsequently. You may want to put the second if nested in the first if
(defn find-min[nums]
(loop [smallest 1000000 i 0]
(if (= (count nums) i)
smallest
(if (< (nums i) smallest)
(recur (nums i) (inc i))
(recur smallest (inc i))))))
Related
I am trying to implement a solution for minimum-swaps required to sort an array in clojure.
The code works, but takes about a second to solve for the 7 element vector, which is very poor compared to a similar solution in Java. (edited)
I already tried providing the explicit types, but doesnt seem to make a difference
I tried using transients, but has an open bug for subvec, that I am using in my solution- https://dev.clojure.org/jira/browse/CLJ-787
Any pointers on how I can optimize the solution?
;; Find minimumSwaps required to sort the array. The algorithm, starts by iterating from 0 to n-1. In each iteration, it places the least element in the ith position.
(defn minimumSwaps [input]
(loop [mv input, i (long 0), swap-count (long 0)]
(if (< i (count input))
(let [min-elem (apply min (drop i mv))]
(if (not= min-elem (mv i))
(recur (swap-arr mv i min-elem),
(unchecked-inc i),
(unchecked-inc swap-count))
(recur mv,
(unchecked-inc i),
swap-count)))
swap-count)))
(defn swap-arr [vec x min-elem]
(let [y (long (.indexOf vec min-elem))]
(assoc vec x (vec y) y (vec x))))
(time (println (minimumSwaps [7 6 5 4 3 2 1])))
There are a few things that can be improved in your solution, both algorithmically and efficiency-wise. The main improvement is to remember both the minimal element in the vector and its position when you search for it. This allows you to not search for the minimal element again with .indexOf.
Here's my revised solution that is ~4 times faster:
(defn swap-arr [v x y]
(assoc v x (v y) y (v x)))
(defn find-min-and-position-in-vector [v, ^long start-from]
(let [size (count v)]
(loop [i start-from, min-so-far (long (nth v start-from)), min-pos start-from]
(if (< i size)
(let [x (long (nth v i))]
(if (< x min-so-far)
(recur (inc i) x i)
(recur (inc i) min-so-far min-pos)))
[min-so-far min-pos]))))
(defn minimumSwaps [input]
(loop [mv input, i (long 0), swap-count (long 0)]
(if (< i (count input))
(let [[min-elem min-pos] (find-min-and-position-in-vector mv i)]
(if (not= min-elem (mv i))
(recur (swap-arr mv i min-pos),
(inc i),
(inc swap-count))
(recur mv,
(inc i),
swap-count)))
swap-count)))
To understand where are the performance bottlenecks in your program, it is better to use https://github.com/clojure-goes-fast/clj-async-profiler rather than to guess.
Notice how I dropped unchecked-* stuff from your code. It is not as important here, and it is easy to get it wrong. If you want to use them for performance, make sure to check the resulting bytecode with a decompiler: https://github.com/clojure-goes-fast/clj-java-decompiler
A similar implementation in java, runs almost in half the time.
That's actually fairly good for Clojure, given that you use immutable vectors where in Java you probably use arrays. After rewriting the Clojure solution to arrays, the performance would be almost the same.
Trying to define a factors function that will return a vector of all the factors of a number using loop/recur.
;; `prime?` borrowed from https://swizec.com/blog/comparing-clojure-and-node-js-for-speed/swizec/1593
(defn prime? [n]
(if (even? n) false
(let [root (num (int (Math/sqrt n)))]
(loop [i 3] (if (> i root) true
(if (zero? (mod n i)) false
(recur (+ i 2))))))))
(defn factors [x] (
(loop [n x i 2 acc []]
(if (prime? n) (conj acc n)
(if (zero? (mod n i)) (recur (/ n i) 2 (conj acc i))
(recur n (inc i) acc))))))
But I keep running into the following error:
ArityException Wrong number of args (0) passed to: PersistentVector clojure.lang.AFn.throwArity
I must be missing something obvious here. Any suggestions are much appreciated!
Let me move the whitespace in your code so it's obvious to you what is wrong:
(defn factors [x]
((loop [n x i 2 acc []]
(if (prime? n) (conj acc n)
(if (zero? (mod n i)) (recur (/ n i) 2 (conj acc i))
(recur n (inc i) acc))))))
You see that weird (( at the start of your function? What's that all about? Remember that in Clojure, as in lisps in general, parentheses are not a grouping construct! They are a function-call mechanism, and you can't just throw extras in for fun. Here, what you wrote has the following meaning:
Run this loop that will compute a vector.
Call the resulting value as a function, passing it no arguments.
Trying to define a factors function that will return a vector of all the factors of a number using loop/recur.
;; `prime?` borrowed from https://swizec.com/blog/comparing-clojure-and-node-js-for-speed/swizec/1593
(defn prime? [n]
(if (even? n) false
(let [root (num (int (Math/sqrt n)))]
(loop [i 3] (if (> i root) true
(if (zero? (mod n i)) false
(recur (+ i 2))))))))
(defn factors [x] (
(loop [n x i 2 acc []]
(if (prime? n) (conj acc n)
(if (zero? (mod n i)) (recur (/ n i) 2 (conj acc i))
(recur n (inc i) acc))))))
But I keep running into the following error:
ArityException Wrong number of args (0) passed to: PersistentVector clojure.lang.AFn.throwArity
I must be missing something obvious here. Any suggestions are much appreciated!
Let me move the whitespace in your code so it's obvious to you what is wrong:
(defn factors [x]
((loop [n x i 2 acc []]
(if (prime? n) (conj acc n)
(if (zero? (mod n i)) (recur (/ n i) 2 (conj acc i))
(recur n (inc i) acc))))))
You see that weird (( at the start of your function? What's that all about? Remember that in Clojure, as in lisps in general, parentheses are not a grouping construct! They are a function-call mechanism, and you can't just throw extras in for fun. Here, what you wrote has the following meaning:
Run this loop that will compute a vector.
Call the resulting value as a function, passing it no arguments.
I don't know why the code below is wrong:
(defn factorial [n]
(loop [n n
acc 1]
(if (zero? n)
acc
(recur (* acc n)(dec n)))))
(= 1 (factorial 1))
How does recur work?
The arguments to the recur are the wrong way round.
n should become (dec n)
acc should become (* acc n)
So it should be
(recur (dec n) (* acc n))
We can recast the given algorithm to see what's going on inside it.
If we represent the pair of arguments as a vector, the function that generates the next pair is
(fn [[n acc]] [(* acc n) (dec n)])
We can generate the endless sequence of possible pairs for a given noby applying iterate to the function above, starting with [no 1].
(fn [no]
(iterate (fn [[n acc]] [(* acc n) (dec n)]) [no 1]))
Applying this to 1 generates
([1 1] [1 0] [0 0] [0 -1] ...)
We stop at element 2, the first with an initial 0, returning the other 0.
If we put the arguments the right way round, we can get the proper factorial thus:
(defn factorial [no]
((comp second first)
(drop-while
(comp not zero? first)
(iterate (fn [[n acc]] [(dec n) (* acc n)]) [no 1]))))
This returns the second element of the first pair in the sequence with a zero first (Duh!).
Hopelessly overcomplicated for normal use, but does it work?
=> (map factorial (range 6))
(1 1 2 6 24 120)
Yes.
I'm learning clojure by going through project euler and am working on problem number 10 (find the sum of all the prime number below two million. I implemented a pretty literal algorithm for the sieve of eratosthenes but it works far too slowly to be useful for up to two million. I tried implementing it with loop-recur to not create any new frames but that didn't have a big impact on performance.
(defn find-primes-sum [last-prime nums]
(loop [p last-prime n nums sum 0]
(println p)
(if (empty? n)
sum
(recur (first n) (doall (remove #(zero? (mod % (first n))) n)) (+ sum (first n))))))
(defn sieve-primes-until [limit]
(find-primes-sum 2 (filter odd? (range 2 (inc limit)))))
(println (sieve-primes-until 2000000))
(set! *unchecked-math* true)
(defmacro iloop [[b t n] & body]
`(loop [~#b]
(when ~t
~#body
(recur ~n))))
(defn count-primes [^long n]
(let [c (inc n)
^booleans prime? (make-array Boolean/TYPE c)]
(iloop [(i 2) (<= i n) (inc i)]
(aset prime? i true))
(iloop [(i 2) (<= (* i i) n) (inc i)]
(if (aget prime? i)
(iloop [(j i) (<= (* i j) n) (inc j)]
(aset prime? (* i j) false))))
(areduce prime? i r 0
(if (aget prime? i)
(inc r)
r))))
This version targets Clojure 1.3.0 alpha. It counts primes up to 1e8 in 2 seconds on my machine. It can be easily altered to collect them. It was originally written to show that you can implement the sieve so that it runs as fast as the comparable Java.
http://dosync.posterous.com/lispers-know-the-value-of-everything-and-the
Personally, I'd structure the code differently. I've got an implementation of this problem that generates a lazy seq of all primes first, then sums the first 2,000,000 items. Takes 16 seconds on clojure 1.2, but it's hardly optimized except for using recur.
You're also doing a lot of unnecessary comparing with your input range; (remove #(zero? (mod % (first n))) n) tests all candidates against all odd numbers, which is nonsense**, especially when you force it with doall. You actually only have to test candidate prime x against all known primes <= sqrt(x) and discard the candidate when you find your first match.
** I just noticed your algorithm is not that stupid, but I'd still recommend you rewrite your algorithm as a lazy seq finds "the next prime" given a seq of previous primes and a candidate number.