Different solutions for Clojure implementation of problem - clojure

Here is a problem Statement :
Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers.
The solution is long,
(defn large [x y]
(if (> x y) x y))
(defn large-3 [x y z]
(if(> (large x y) z) (large x y) z))
(defn small [x y]
(if (< x y) x y))
(defn small-3 [x y z]
(if (< (small x y) z ) (small x y) z))
(defn second-largest [x y z]
(let [greatest (large-3 x y z)
smallest (small-3 x y z)]
(first (filter #(and (> greatest %) (< smallest %)) [x y z]))))
(defn square [a]
(* a a)
)
(defn sum-of-square [x y z]
(+ (square (large-3 x y z)) (square (second-largest x y z))))
Just wanted to know what different/succinct ways this problem can be solved in Clojure.

(defn foo [& xs]
(let [big-xs (take 2 (sort-by - xs))]
(reduce + (map * big-xs big-xs))))

; why only 3? how about N
(defn sum-of-squares [& nums]
(reduce + (map #(* % %) (drop 1 (sort nums)))))
or if you want "the sum of the greatest two numbers:
(defn sum-of-squares [& nums]
(reduce + (map #(* % %) (take 2 (reverse (sort nums))))))
(take 2 (reverse (sort nums))) fromMichał Marczyk's answer.

(See a sequence version of the problem together with a lazy solution in my second update to this answer below.)
(defn square [n]
(* n n))
;; generalises easily to larger numbers of arguments
(defn sum-of-larger-squares [x y z]
(apply + (map square (take 2 (reverse (sort [x y z]))))))
;; shorter; generalises easily if you want
;; 'the sum of the squares of all numbers but n smallest'
(defn sum-of-larger-squares [x y z]
(apply + (map square (drop 1 (sort [x y z])))))
Update:
To expand on the comments from the above, the first version's straighforward generalisation is to this:
(defn sum-of-larger-squares [n & xs]
(apply + (map square (take n (reverse (sort xs))))))
The second version straightforwardly generalises to the version Arthur posted in the meantime:
(defn sum-of-larger-squares [n & xs]
(apply + (map square (drop n (sort xs)))))
Also, I've seen exactly the same problem being solved in Scheme, possibly even on SO... It included some fun solutions, like one which calculated the some of all three squares, then subtracted the smallest square (that's very straightforward to express with Scheme primitives). That's 'unefficient' in that it calculates the one extra square, but it's certainly very readable. Can't seem to find the link now, unfortunately.
Update 2:
In response to Arthur Ulfeldt's comment on the question, a lazy solution to a (hopefully fun) different version of the problem. Code first, explanation below:
(use 'clojure.contrib.seq-utils) ; recently renamed to clojure.contrib.seq
(defn moving-sum-of-smaller-squares [pred n nums]
(map first
(reductions (fn [[current-sum [x :as current-xs]] y]
(if (pred y x)
(let [z (peek current-xs)]
[(+ current-sum (- (* z z)) (* y y))
(vec (sort-by identity pred (conj (pop current-xs) y)))])
[current-sum
current-xs]))
(let [initial-xs (vec (sort-by identity pred (take n nums)))
initial-sum (reduce + (map #(* % %) initial-xs))]
[initial-sum initial-xs])
(drop n nums))))
The clojure.contrib.seq-utils (or c.c.seq) lib is there for the reductions function. iterate could be used instead, but not without some added complexity (unless one would be willing to calculate the length of the seq of numbers to be processed at the start, which would be at odds with the goal of remaining as lazy as possible).
Explanation with example of use:
user> (moving-sum-of-smaller-squares < 2 [9 3 2 1 0 5 3])
(90 13 5 1 1 1)
;; and to prove laziness...
user> (take 2 (moving-sum-of-smaller-squares < 2 (iterate inc 0)))
(1 1)
;; also, 'smaller' means pred-smaller here -- with
;; a different ordering, a different result is obtained
user> (take 10 (moving-sum-of-smaller-squares > 2 (iterate inc 0)))
(1 5 13 25 41 61 85 113 145 181)
Generally, (moving-sum-of-smaller-squares pred n & nums) generates a lazy seq of sums of squares of the n pred-smallest numbers in increasingly long initial fragments of the original seq of numbers, where 'pred-smallest' means smallest with regard to the ordering induced by the predicate pred. With pred = >, the sum of n greatest squares is calculated.
This function uses the trick I mentioned above when describing the Scheme solution which summed three squares, then subtracted the smallest one, and so is able to adjust the running sum by the correct amount without recalculating it at each step.
On the other hand, it does perform a lot of sorting; I find it's not really worthwhile to try and optimise this part, as the seqs being sorted are always n elements long and there's a maximum of one sorting operation at each step (none if the sum doesn't require adjustment).

Related

How to access all of the second elements within a vector that is within a vector?

I have the following structure:
(def m [[120 2] [123 88] [234 77]])
And the value
(def z 10)
I am wanting to access all of the second elements within the smaller vectors (within m) and multiply them by z and then store the result with the first element of the vector.
I.e. do the calculation (* secondvectorelement z)
And the result would look like [120 resultofcalculation]
So far I have tried:
(map #(* (second m) z ))
But I am stuck on this.
TIA.
You can use a for list comphrehension with destructuring:
(for [[fst snd] m] [fst (* snd z)])
Or a different approach with the map and update functions:
(map #(update % 1 * z) m)
user=> (map (fn [v] [(first v) (* z (second v))]) m)
([120 20] [123 880] [234 770])
Try this:
(map #(vector (first %) (* (second %) z)) m)
In my opinion, no need to def z, so:
(map #(vector (first %) (* (second %) 10)) m)
Edit: I like #erdos' answer better though
A slightly different approach:
(conj [] (apply min (map #(first %) m)) (apply * (conj (map #(second %) m) z)))
If we apply the above to OP's data we get
[120 135520]

Clojure - call a function over and over using the result as an argument

I have a simple function that adds numbers together and multiplies them.
(defn add-and-multiply [x y z]
(let [add (+ x y z)
mult (* x y z)]
(println "Add: " add)
(println "Mult: " mult)))
(add-and-multiply 1 1 2)
Add: 4
Mult: 2
nil
How would I call add-and-multiply again with the x argument now being the result of add (4), the y argument being the result of mult (2) and the z argument being the same (2).
How could I then repeat this process 100 times and then print the final values of add and mult?
Any help would be much appreciated. Thanks
I would not be surprised to find that the result after 100 iterations is too large to fit into RAM. Unless I am misunderstanding the formula, this is a lot like computing x*(x^2)*(x^4)*(x^8)...up to x^(2^100), which simplifies to x^(2^200). It's actually larger because there is an adding step as well, but I think that is relatively minor compared to the iterative multiplication. 2^200 is pretty big already, but you could compute it if you needed to.
However, 2^(2^200) is tremendously vast. Obviously you need 2^200 bits of RAM, at a minimum, to hold that number without losing precision. A typical desktop computer has perhaps 16GB of RAM, which is 2^30 (a billion) * 16 gigs * 8 bits/byte = 2^37 bits of storage. You would need not just one desktop computer to store this, but 2^163 of them. Again, I cannot emphasize enough just how large a number that is. If every grain of sand on the planet were a desktop computer with 16GB of RAM, you would not be close to being able to store this number.
So, I would say you should probably figure out a different way to solve whatever your real problem is, assuming you can't afford to buy whole galaxies worth of computing power.
That said, regarding the mechanics of how to generalize (f (f (f (f x)))) to an arbitrary number of calls to f, the other answers have given you a good explanation of how to use iterate, and will serve you well if you choose an f whose runtime is more manageable.
If you change add-and-multiply to return the two results:
(defn add-and-multiply [x y z]
(let [add (+ x y z)
mult (* x y z)]
[add mult]))
then you can use iterate to generate successive applications. Use first and drop to select the result you want e.g.
(first (drop 10 (iterate (fn [[x y]] (add-and-multiply x y 2)) [(bigint 1) (bigint 2)])))
;; have a look at juxt
((juxt + * (fn [_ _ x] x)) 1 1 2) [4 2 2]
;; you can then use it like this:
(second (iterate (fn [v]
(apply (juxt + * (fn [_ _ x] x)) v)) [1 1 2])) ;; [4 2 2]
;; however it overflows quickly, so use +' *'
;; also, put it into a function
(defn add-and-multiply [times nb]
(nth (iterate (fn [v]
(apply (juxt +' *' (fn [_ _ x] x)) v)) nb) times))
(add-and-multiply 10 [1 1 2]) ;; [7983075120467448500799760620188561621081118348584N 20456985749705433596250191236583540578087736309004220218432871989995224183078912N 2]
A concise way to do this is
(defn compute [n]
(let [step (fn [[x y z :as all]] [(reduce +' all) (reduce *' all) z])]
(nth (iterate step [1 1 2]) n)))
This runs out of steam on my laptop at about n = 35.
Spelling out the computation helps a little:
(defn compute [n]
(loop [x 1, y 1, z 2, n n]
(if (zero? n)
[x y z]
(recur (+' x y z) (*' x y z) z (dec n)))))
But life is too short to wait for either of these to compute the result for n = 100.
We could pull z out of the computation either way, since it stays constant at 2. It doesn't save much to do so, so I chose to stay with the question's prescription.

Standard Deviation in clojure

I am trying to write a function in clojure to find the standard deviation of a sequence (vector). So far I have defined a function to find the average of a set of numbers, but I am having an issue with a couple of things.
First I am confused over how to use a square root and powers in clojure. Second I am trying to figure out how to pull out each element individually out the vector and subtract the mean from it and then square it.
So far this is my function
(defn mean [a] (/ (reduce + a) (count a)))
(defn standarddev [a] (Math/sqrt (/ (reduce + (map square #(- % (mean a) a))) (- (count a) 1 ))))
As long as you have a double, you can use Java's Math class (https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html) to perform calculations like sqrt. You don't need to do anything special to access the Math class, because Clojure make all java.lang classes available to you w/o import.
You are pretty close.
Assuming you already have the following functions
(defn square [n] (* n n))
(defn mean [a] (/ (reduce + a) (count a)))
2 problems with your standarddev function
(defn standarddev [a] (Math/sqrt (/ (map square (map - a (mean a))) (- (count a) 1 ))))
1) (map - a (mean a))
Doesn't work because you are subtracting a "number" from a "vector".
To fix repeat (mean a) as many times as there are elements in "a"
Easiest and by no means efficient solution would be
(map - a (repeat (mean a)))
2) (map square (map - a (mean a))) Doesn't work because of #1 above and because map returns a "vector".
To fix sum the elements of the vector
(reduce + (map square (map - a (repeat (mean a)))))
Your standard dev function should now be
(defn standarddev [a]
(Math/sqrt (/
(reduce + (map square (map - a (repeat (mean a)))))
(- (count a) 1 ))))
You can gently increase performance by getting rid of the map altogether
(def square #(* % %))
(defn standard-deviation
[a]
(let [mn (mean a)]
(Math/sqrt
(/ (reduce #(+ %1 (square (- %2 mn))) 0 a)
(dec (count a))))))
First I am confused over how to use a square root and powers in clojure.
To square something, just multiply it by itself:
(defn square [n]
(* n n))
If you want a power higher than 2, you could also use an exponentiation function:
(defn exp [x n]
(reduce * (repeat n x)))
Second I am trying to figure out how to pull out each element individually out the vector and subtract the mean from it and then square it.
The Clojure (functional) way of iterating through a seq is to use map. Map takes a function and a collection and returns the result of applying that function to each element of the collection.
(defn squares [avg coll] (map #(square (- % avg)) coll))
Final standard-deviation function, using the above 2 functions and your mean:
(defn standard-deviation [coll]
(let [avg (mean coll)
squares (squares avg coll)
total (count coll)]
(Math/sqrt (/ (reduce + squares) (- total 1)))))
inspiration from: https://github.com/clojure-cookbook/clojure-cookbook/blob/master/01_primitive-data/1-20_simple-statistics.asciidoc
Corrected sample standard deviation, same as in R sd function
(defn sd [abc]
(Math/sqrt
(/ (reduce + (map #(* % %)
(map #(- % (/ (reduce + abc) (count abc))) abc)))
(dec (count abc))
)
)
)

Given a partially ordered set, remove all smaller items

I'm struggling to find a beautiful, idiomatic way to write a function
(defn remove-smaller
[coll partial-order-fn]
___
)
where partial-order-fn takes two arguments and return -1 0 or 1 is they are comparable (resp. smaller, equal, bigger) or nil otherwise.
The result of remove-smaller should be coll, with all items that are smaller than any other item in coll are removed.
Example: If we defined a partial order such as numbers are compared normally, letters too, but a letter and a number are not comparable:
1 < 2 a < t 2 ? a
Then we would have:
(remove-smaller [1 9 a f 3 4 z])
==> [9 z]
(defn partial-compare [x y]
(when (= (type x) (type y))
(compare x y)))
(defn remove-smaller [coll partial-order-fn]
(filter
(fn [x] (every? #(let [p (partial-order-fn x %)]
(or (nil? p) (>= p 0)))
coll))
coll))
(defn -main []
(remove-smaller [1 9 \a \f 3 4 \z] partial-compare))
This outputs (9 \z), which is correct unless you want the return value to be of the same type as coll.
In practice I might just use tom's answer, since no algorithm can guarantee better than O(n^2) worst-case performance and it's easy to read. But if performance matters, choosing an algorithm that is always n^2 isn't good if you can avoid it; the below solution avoids re-iterating over any items which are known not to be maxes, and therefore can be as good as O(n) if the set turns out to actually be totally ordered. (of course, this relies on transitivity of the ordering relation, but since you call this a partial order that's implied)
(defn remove-smaller [cmp coll]
(reduce (fn [maxes x]
(let [[acc keep-x]
,,(reduce (fn [[acc keep-x] [max diff]]
(cond (neg? diff) [(conj acc max) false]
(pos? diff) [acc keep-x]
:else [(conj acc max) keep-x]))
[[] true], (map #(list % (or (cmp x %) 0))
maxes))]
(if keep-x
(conj acc x)
acc)))
(), coll))
(def data [1 9 \a \f 3 4 \z])
(defn my-fn [x y]
(when (= (type x) (type y))
(compare x y)))
(defn remove-smaller [coll partial-order-fn]
(mapv #(->> % (sort partial-order-fn) last) (vals (group-by type data))))
(remove-smaller data my-fn)
;=> [9 \z]
Potentially the order of the remaining items might differ to the input collection, but there is no order between the equality 'partitions'

find the n-tuples of all integers below m whose sum is a prime

I am going through the Clojure in Action book and code similar to that below is given for a function that returns all pairs of numbers below m whose sum is a prime (assume prime? is given):
(defn pairs-for-primes [m]
(let [z (range 0 m)]
(for [a z b z :when (prime? (+ a b))]
(list a b))))
How would one generalize that to return the n-tuples of all numbers below m whose sum is a prime?
(defn all-ntuples-below [n m]
...
for can be used for a sort of "special case" of cartesian product, where you know the sets in advance at compile time. Since you don't actually know the sets you want the product of, you need to use a real cartesian-product function. For example, with clojure.math.combinatorics, you could write
(defn pairs-for-primes [m n]
(let [z (range 0 m)
tuples (apply cartesian-product (repeat n z))]
(filter #(prime? (apply + %)) tuples)))
But perhaps your question is about how to implement a cartesian product? It's not that hard, although the version below is not terribly performant:
(defn cartesian-product [sets]
(cond (empty? sets) (list (list))
(not (next sets)) (map list (first sets))
:else (for [x (first sets)
tuple (cartesian-product (rest sets))]
(cons x tuple))))
You can use take to do that (as pairs-for-primes returns a sequence take will only cause it to calculate the number of items required)
(defn all-ntuples-below [n m]
(take n (pairs-for-primes m)))