I'm trying to calculate the sine of an angle based on this formula, and I'm feeding two parameters to this function: the angle's degrees and the amount of terms to compute:
(defn factorial [n]
(if (= n 1) 1
(* n (factorial (dec n)))))
(defn sine-terms [deg terms]
(let [pi 3.14159
radians (* deg (/ 180 pi))]
(loop [a 0
sine 0]
(if (= a terms) sine
(let
[current-no (+ (* 2 a) 1)
temp
(/
(Math/pow radians current-no)
(factorial current-no))]
(recur
(inc a)
(if (= (mod a 2) 0)
(+ sine temp)
(- sine temp))))))))
If I run this code, with deg as 30 and terms as 10, it outputs:
-2.4237952736426853E44
Which isn't even close to 0.5, which is the sine to 30 degrees. If I put a print at the beginning of the outer loop to print sine after every iteration, it outputs this:
0
1718.8748372639334
-8.46409695587649E8
1.250365792948E14
-8.7957538602188431E18
3.609314026964587E23
-9.694265426923215E27
1.835997368923122E32
-2.583053077880347E36
2.8057167260702447E40
-2.4237952736426853E44
The output gets smaller and smaller each time: I'm pretty sure that the loop is throwing away the sine generated, and replacing it with 0, for some reason. I'm not sure if this is a problem with the code itself (which I doubt) or a bug in Clojure itself.
Note that the values are getting much larger, not much smaller. 2.8057167260702447E40 is 2.8 times 10^40.
The cause of this problem is fairly clear: 180/pi is much larger than the intended pi/180.
As an aside, when debugging problems in general, it is much more productive to start from the assumption that a bug in the language is what is doubtworthy, and that a bug in your own code is tremendously more likely.
Related
I've faced a problem that how to write a clojure function to get one solution of the equation u + v + x + y + z = 100, all variables are positive integers.
The function works like this , if we run (fun 100)then we get one solution (such as [1 10 49 3 37]), if we run (fun 100)once more, we got another solution (maybe [29 46 7 12 6])
Josh's answer mentions a smart algorithm that doesn't waste time brute-forcing dead-end paths. This algorithm is quite simple to write, by tracking the outstanding sum and only choosing numbers no larger than what remains.
(defn sums-to [n total]
(case n
1 [[total]]
(for [i (range (inc total))
solution (sums-to (dec n) (- total i))]
(cons i solution))))
It gets the same answers as the brute-force approach, and instead of ten minutes it takes ten seconds to find them:
user> (time (count (sums-to 5 100)))
"Elapsed time: 12734.779787 msecs"
4598126
This can be achieved with the for list comprehension. Given that you have five variables, there are 10B operations that must be performed, and to brute force it takes a bit of time (a few minutes at least on a core i7 machine. Your best bet is to seek a smart algorithm which will say, for example, that when x is 98, y is 1, and z is 1, then there's no use in looping through u and v, as they must be zero. But, here is the brute force approach:
(def solns (for [x (range 101)
y (range 101)
z (range 101)
u (range 101)
v (range 101)
:when (= 100 (+ x y z u v))]
[x y z u v]))
Now, you have a lazy list of all solutions. Be careful with this, as it's very computationally intensive to perform a (count solns) or (rand-nth solns) (it will take maybe 10 minutes on a modern machine), as the whole list will be realized. Once the list is realized though, you can easily get truly random solutions with (rand-nth solns) as the computation is already done. There are 4,598,126 solutions.
Finally I got the answer myself:
(defn fun [total-sum]
(let [init-part-list (repeat 4 1)
sum (atom (- total-sum (apply + init-part-list)))
part-list (map #(let [r (rand-int #sum)]
(reset! sum (- #sum r))
(+ % r))
init-part-list)]
(cons (- total-sum (apply + part-list)) part-list)))
It really works and takes less than 1 msecs to get the result
=> (time (fun 100))
"Elapsed time: 0.070562 msecs"
But the code look a little bit complicated, can anyone show us a more concise solution?
I tried to find a list of perfect number in this way:
(defn classify [num]
(let [factors (->> (range 1 (inc num))
(filter #(zero? (rem num %))))
sum (reduce + factors)
aliquot-sum (- sum num)]
(cond
(= aliquot-sum num) :perfect
(> aliquot-sum num) :abundant
(< aliquot-sum num) :deficient)))
(defn is-p [n]
(= :perfect (classify n)))
(defn list-perfect [n]
(filter is-p (range 1 (inc n))))
Question:
How to build a lazy sequence of perfect numbers, so that I can use (take n ...) to easily get a list.
Is this code idiomatic and efficient? Any improvement?
Thanks in advance.
Your algorithm is very inefficient, it's O(n).
For a quick win, you can immediately reduce the range by a half, as you won't ever have factors that are greater than the number you're testing divided by 2.
So change it to:
(defn classify [num]
(let [factors (->> (range 1 (max 2 (inc (quot num 2))))
;; ...
However... you can change it to O(sqrt n) which is magnitudes faster. See my timings below.
The real efficiency is noticing that factors are in pairs of [x (quot num x)] and then only check the first (sqrt num) (or slightly over):
(defn perfect? [n]
(let [r (range 2 (+ 2 (int (Math/sqrt n))))
s (set (mapcat #(if (zero? (rem n %))
[% (quot n %)])
r))
t (reduce + 1 s)]
(= n t)))
I've split it into separate calculations so you can verify each stage.
The range can be reduced from 2..((sqrt n) + 2), and initialise the reduction with 1 (which is always a factor).
This changes the problem from an O(n) to O(sqrt n), so if you're checking large numbers, makes a vast difference.
As an illustration here are some times on larger values for n on my MBP:
n "n/2" "sqrt n"
33550336 1,172.5ms 2.85ms
8589869056 274,346.6ms 16.76ms
137438691328 didn't time 44.27ms
so using root version was 16,369 times faster for the 6th perfect number. See http://en.wikipedia.org/wiki/List_of_perfect_numbers for more details.
EDIT:
Why (int (root n)) + 2? And why `[x (quot n x)]?
When you work out the factors of a number n, then if you find one (say, a), then n/a is also a factor (call it b) because n = a * b
e.g. looking at 28, the first relevant factor is 2, and clearly 28/2 = 14 is also a factor. So you don't need to check 14, you already know it's a factor from the fact that 2 is.
as we're incrementally checking numbers from 2 upwards, we're incidentally finding the higher numbers coming down:
2 is a factor, 28 / 2 = 14 -> [a, b] = [2, 14]
4 is a factor, 28 / 4 = 7 -> [a, b] = [4, 7]
7 is a factor, 28 / 7 = 4 -> [a, b] = [7, 4] - wait a minute...
The [a,b] pairs here are the [% (quot n %)] in the mapcat function, e.g. when the range is currently iterating the value 2, then % is 2 inside the fuction, and so (quot n %) is (quot 28 2) which is 14, thus [% (quot n %)] is simply the vector [2 14], which then gets added to the set after being flattened to 2 and 14 as values. Later, when the range value is 4, then [% (quot n %)] is [4 (quot 28 4)] which is [4 7], and again is flattened by mapcat as the numbers 4 and 7.
So we add each pair of numbers (flattened via mapcat) to our set, include the number 1, and end up with #{1 2 14 4 7}, which are the factors of 28. (Actually, I don't put 1 in the set as I don't need to, instead I start the summing reduction at 1, which is same effect).
But at what point do they turn around? i.e. when do we know that [7,4] will already have been included in the set as [4,7]?
clearly it's when a > b, because in finding the lowest numbers we always find the highest number with it, so we can finish checking at this point.
but what is this point? it's simple, if a perfect number were a square number, then a and b would be equal, i.e. a*a = n, so a = sqrt(n).
Thus the highest value of a we need to check is the whole number that is larger than the root of n.
e.g. for 28, sqrt(28) = 5.292, so we have to check 6 to be sure that we've included the lowest number possible that could be a factor that has a paired factor.
so we need (int (sqrt n)) + 1.
I always do this in case the root calculation is 1.9999999999... and rounds wrong way, so adding 1 more ensures you eliminate any rounding errors.
but in a range, if you want to include that number you have to add 1 more to it (range drops the high number, (range 6) = (0 1 2 3 4 5)), hence why it adds 2 to the value: 1 for the range, 1 to ensure it's above the rounded down root.
Although, after saying this, I've tested perfect numbers up to 2305843008139952128 and it works with +1 instead of +2, not that it's a massive saving. Probably because non of the perfect numbers are close to perfect squares in ones I checked, so there's no rounding error in (int (sqrt n)).
If you're interested in perfect numbers, I'd recommend reading http://britton.disted.camosun.bc.ca/perfect_number/lesson1.html
list-perfect is already lazy due to your usage of filter:
(filter pred coll)
Returns a lazy sequence of the items in coll for which
(pred item) returns true. pred must be free of side-effects.
Whether code is idiomatic or not might be a matter of opinion (and hence off-topic), but it looks good enough from my perspective.
Hi I am programming in clojure and though the problem of modulo inverse has nothing to do with language i am stuck at this code -
(defn EulerDiv [x p]
(let [ToMod (+ p 2)]
(loop [num 1 toPow (int p) numDouble x]
(if (= 0 toPow)
num
(let [numDouble2 (rem (* numDouble numDouble) ToMod)
halfToPow (int (/ toPow 2))]
(if (odd? toPow)
(recur (rem (* num numDouble) ToMod)
halfToPow
numDouble2)
(recur num halfToPow numDouble2))
))))
)
It seems to give me right answers for small Primes but when i am using it in a problem with Bigger primes i am getting answers other than result like :
(= 2 (mod (* 4 (EulerDiv 2 (- 3 2))) 3))
This prints true
(def ToMod (+ 10e8 7))
( = 1 (int (mod (* 2 (EulerDiv 2 (- ToMod 2))) ToMod)) )
This prints false.
Also there is rem and mod in clojure.
mod makes the output positive and hence i can not use it in between the calculations.
It is a programming contest but this is just part of solution and this info of modulo inverse was also provided in the problem page.
The problem is that of programming calculator grammar for evaluating evpressions like 4/-2/(2 + 8)
You are straying from integer arithmetic.
Given integers, the / function can produce rationals: (/ 1 2) is 1/2, not 0.
And 1e9 is 1.0E9, a double, not an integer.
There are appropriate substitutes available. Look at the arithmetic section here for an integer division function, and at the cast section for something to convert a number to an integer.
All the best!
The code below draws me the sine wave throughout the screen, and beyond.
However, I want that x never exceeds (width). At that point, the window should be cleared, and the wave should be drawn again, starting at 0. I tried
(set-state! :x (mod (seq->stream x) (width)))
but it didn't work. I checked some examples, tried some code which made use of checking whether (> x (width)), tried to put the logic into the draw function, but they don't work either.
I would like to draw a continuous waveform (like an electrocardiogram) on a limited display. I would appreciate any help.
(ns soso.core
(:require [quil.core :refer :all]
[quil.helpers.seqs :refer [seq->stream range-incl]]))
(defn setup []
(smooth)
(frame-rate 100)
(background 255)
(let [x (range-incl)]
(set-state! :x (seq->stream x))))
(defn draw []
(stroke 0)
(stroke-weight 2)
(let [x ((state :x))
y (round (* 100 (abs (sin x))))]
(ellipse x y 4 4)))
Edit
When I tried to put the logic into the draw function, I wrote (set-state! :x 0) in the setup function, and put the following code into the draw function:
(let [x (if (> ((state :x)) 10)
0
(inc ((state :x))))])
But it didn't work, and didn't throw any error in any of the nrepl buffers. To see what happened, I tried this code in the user repl:
(let [x 0]
(take 20
(if (> x 10)
0
(inc x))))
Even if I tried this code by wrapping the if statement inside (into '()), the code complained with: "IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom". It is the same with:
(loop [x 0]
(if (> x 10)
0
(recur (inc x))))
What is wrong with this if statement? The clojure api says that if tests the test condition, and then evaluates and yields then or else branches, accordingly. If it yields, it should spit out that integer, which in turn gets added to the list, which in turn should be listed by take function, I think.
Something more like this seems to give the effect you are looking for.
(defn draw []
(stroke 0)
(stroke-weight 2)
(let [x ((state :x))
y (+ 100 (* 100 (sin (/ x 100))))]
(ellipse (mod x (width)) y 4 4)))
Couple of issues you are encountering:
The input to sin is a floating value in radians. My hackery of divide by 100 here just makes sure that we're getting a nice continuous output. Practically if you want to cycle every n pixels you need to use 2 PI / n to adjust x.
Rounding off the value is going to give you points, as the domain of sin is 1 to -1. Here I'm adjusting by adding on 100.
Where you fiddle with x will depend on the exact requirement. Here I'm simply wrapping your x value by taking it's modulus in the draw function.
Hope this helps.
I'm doing Project Euler to learn Clojure.
The purpose of this function is to calculate the lcm of the set of integers from 1 to m.
(lcm 10) returns 2520
This is a rather brute-force way of doing this. In theory, we go through each number from m to infinity and return the first number for which all values 1 through m divide that number evenly.
If I understand what 'lazy' means correctly (and if I am truly being lazy here), then this should run in constant space. There's no need to hold more than the list of numbers from 1 to m and 1 value from the infinite set of numbers that we're looping through.
I am, however, getting a java.lang.OutOfMemoryError: Java heap space at m values greater than 17.
(defn lcm [m]
(let [xs (range 1 (+ m 1))]
(first (for [x (iterate inc m) :when
(empty?
(filter (fn [y] (not (factor-of? y x))) xs))] x))))
Thanks!
As far as I can tell, your code is in fact lazy (also in the sense that it's in no hurry to reach the answer... ;-) -- see below), however it generates piles upon piles upon piles of garbage. Just consider that (lvm 17) amounts to asking for over 1.2 million lazy filtering operations on (range 1 18). I can't reproduce your out-of-memory problem, but I'd tentatively conjecture it might be an issue with your memory & GC settings.
Now although I realise that your question is not actually about algorithms, note that the production of all that garbage, the carrying out of all those filtering operations etc. not only utterly destroy the space complexity of this, but the time complexity as well. Why not use an actual LCM algorithm? Like the one exploiting lcm(X) = gcd(X) / product(X) for X a set of natural numbers. The GCD can be calculated with Euclid's algorithm.
(defn gcd
([x y]
(cond (zero? x) y
(< y x) (recur y x)
:else (recur x (rem y x))))
([x y & zs]
(reduce gcd (gcd x y) zs)))
(defn lcm
([x y] (/ (* x y) (gcd x y)))
([x y & zs]
(reduce lcm (lcm x y) zs)))
With the above in place, (apply lcm (range 1 18)) will give you your answer in short order.
I'm getting the same OutOfMemoryError on Clojure 1.1, but not on 1.2.
I imagine it's a bug in 1.1 where for holds on to more garbage than necessary.
So I suppose the fix is to upgrade Clojure. Or to use Michal's algorithm for an answer in a fraction of the time.
While I accept that this is acknowledged to be brute force, I shiver at the idea. For the set of consecutive numbers that runs up to 50, the lcm is 3099044504245996706400. Do you really want a loop that tests every number up to that point to identify the lcm of the set?
Other schemes would seem far better. For example, factor each member of the sequence, then simply count the maximum number of occurrences of each prime factor. Or, build a simple prime sieve, that simultaneously factors the set of numbers, while allowing you to count factor multiplicities.
These schemes can be written to be highly efficient. Or you can use brute force. The latter seems silly here.
Michal is correct about the problem. A sieve will be a little bit faster, since no gcd calculations are needed:
EDIT: This code is actually horribly wrong. I've left it here to remind myself to check my work twice if I have such a hangover.
(ns euler (:use clojure.contrib.math))
(defn sieve
([m] (sieve m (vec (repeat (+ 1 m) true)) 2))
([m sieve-vector factor]
(if (< factor m)
(if (sieve-vector factor)
(recur m
(reduce #(assoc %1 %2 false)
sieve-vector
(range (* 2 factor) (+ 1 m) factor))
(inc factor))
(recur m sieve-vector (inc factor)))
sieve-vector)))
(defn primes [m] (map key (filter val (seq (zipmap (range 2 m) (subvec (sieve m) 2))))))
(defn prime-Powers-LCM [m] (zipmap (primes m) (map #(quot m %) (primes m))))
(defn LCM [m] (reduce #(* %1 (expt (key %2) (val %2))) 1 (seq (prime-Powers-LCM m))))