How to check whether a number is Fibonacci number in Clojure? - clojure

Input: a positive integer.
Output: true / false based on test.
Here is my attempt:
(defn is-a-fib? [x]
"Check whether x is a fibonacci number.
Algorithm: test whether 5x^2+4 or 5x^2-4 is a perfect square."
(let [a (+' (*' (Math/pow x 2) 5) 4) ; 5x^2+4
b (-' (*' (Math/pow x 2) 5) 4) ; 5x^2-4
sqrt-a (Math/sqrt a)
sqrt-b (Math/sqrt b)]
(or (== (*' sqrt-a sqrt-a)
(*' (Math/floor sqrt-a) (Math/floor sqrt-a))) ; Test whether n is a perfect square
(== (*' sqrt-b sqrt-b)
(*' (Math/floor sqrt-b) (Math/floor sqrt-b))))))
The problem is: this code doesn't work for a large number. I think it may cause stack overflow.
Is there a better way?

The Math/pow, Math/sqrt, and Math/floor operations work on doubles which have a limited range of precision, and operations on them will have rounding errors.
If you look at it in this light, things may derail simply owing to rounding, but they will really go wrong when you've exhausted the precision (15–17 decimal digits).
This first nth Fibonnacci where this algorithm gives a false positive for the subsequent integer is for the 16-digit integer associated with n = 74.
(is-a-fib? 1304969544928657)
=> true
(is-a-fib? 1304969544928658)
=> true
Edit: Adding arbitrary precision solution that avoids doubles:
The main difficulty is the lack of an integer square root algorithm.
This Java implementation can be translated to Clojure:
(defn integer-sqrt [n]
(let [n (biginteger n)]
(loop [a BigInteger/ONE
b (-> n (.shiftRight 5) (.add (biginteger 8)))]
(if (>= (.compareTo b a) 0)
(let [mid (-> a (.add b) (.shiftRight 1))]
(if (pos? (-> mid (.multiply mid) (.compareTo n)))
(recur a (.subtract mid BigInteger/ONE))
(recur (.add mid BigInteger/ONE) b)))
(dec a)))))
With that in place, you can define an arbitrary-precision perfect square test:
(defn perfect-square? [n]
(let [x (integer-sqrt n)]
(= (*' x x) n)))
And update your implementation to use it:
(defn is-a-fib? [x]
"Check whether x is a fibonacci number.
Algorithm: test whether 5x^2+4 or 5x^2-4 is a perfect square."
(let [a (+' (*' (*' x x) 5) 4) ; 5x^2+4
b (-' (*' (*' x x) 5) 4)] ; 5x^2-4
(or (perfect-square? a)
(perfect-square? b))))

Related

Getting Execution error (StackOverflowError) when evaluating a function on larger range of values

I'm learning Clojure and solving exercises from SICP book in the process. I get this error when evaluating (search-for-primes 1001 10000) but when called on smaller values (search-for-primes 101 1000) it works fine.
This seems to be a memory issue but I'm unable to zero in on the cause of it. Would love your help. Thank you. Below is the code.
(defn square [x]
(* x x))
(defn divides? [a b]
(= (rem b a) 0))
(defn find-divisor [n test-divisor]
(cond
(> (square test-divisor) n) n
(divides? test-divisor n) test-divisor
:else (find-divisor n (+ test-divisor 1))))
(defn smallest-divisor [n]
(find-divisor n 2))
;;return true if prime
(defn prime?
[n]
(= n (smallest-divisor n)))
;;return the first of the three consecutive prime numbers
(defn search-for-primes [low high]
(if (< low high)
(cond
(and (prime? low) (prime? (+ low 2)) (prime? (+ low 4))) low
:else (search-for-primes (+ low 2) high))))
You don't show the actual error you're getting, but I'll guess that it has something to do with the stack overflowing.
Unlike Scheme, Clojure does not support tail call elimination, so you probably need to look at loop/recur, see https://clojuredocs.org/clojure.core/loop for example.

Why recursive function is not memoized

Hello I can't wrap my head around this problem:
(defn integrate
"Finding the definite integral from 0 to stop"
([f dx]
(let [itg (memoize
(fn [itg stop n]
(if (<= n 0)
0
(+ (let [b (* n dx) a (- b dx)]
(println "[DEBUG] stop = " stop " and n =" n)
(* (- b a) (/ (+ (f a) (f b)) 2))
)
(itg itg stop (dec n))))))
itg (partial itg itg)]
(fn [x] (itg x (quot x dx))))))
(time ((integrate (fn [x] (* x x)) 0.1) 5))
(time ((integrate (fn [x] (* x x)) 0.1) 5))
I expect that the 2nd time I call this function, it should hit the memoized result, but it just recalculates the whole integral the second time and prints the DEBUG messages all over again.
Why this happens? How to fix this?
Two problems. 1) Each call to integrate creates a fresh memoized function, so a second call to integrate won't reuse any results computed by the first call. 2) One of the parameters to the memoized function is itself a function. It is not true that (= (fn []) (fn [])), so the memo might not match as often as you hope.
You can find a good write-up on this issue here: https://quanttype.net/posts/2020-09-20-local-memoized-recursive-functions.html

how to Replace an Integer with string 20 percent of the time Clojure

I need to replace an integer with a string in clojure but only for 20% of the outputted integers.
(defn factor5 [x]
(if (= (mod x 3) (mod x 5) 0) "BuzzFizz"
(if (= (mod x 5) 0) "buzz"
(if (= (mod x 3) 0) "fizz" x))))
here i have a fizzbuzz program which prints out "fizz" if the number is a multiple of 3 or "buzz" if it is a multiple of 5 and "BuzzFizz" is printed if is a multiple of both. if an integer is neither of the above multiplies the integer gets printed. What i need is to print "Boom" instead of the integer but only for 20% of the integers.
some pseudo code
if(x == int){
print out Boom instead of x only for 20% }
else{
print out x}
I have very limited exprience in clojure as my pseudocode is java based
Please see the Clojure Cheatsheet for a comprehensive listing of functions.
The one you want is rand, and a test like:
(if (< (rand) 0.2) ....)
if you want the decision made randomly you could use one of the rand runctions in an if statement like so:
user> (defn x20% [x]
(if (rand-nth [true false false false false])
"Boom"
x))
#'user/x20%
user> (x20% 5)
5
user> (x20% 5)
5
user> (x20% 5)
"Boom"
user> (x20% 5)
5
there are also rand and rand-int. which you use is somewhat a matter of style and the specifics of your function:
user> (> 2 (rand-int 10))
true
user> (> 2 (rand-int 10))
true
user> (> 2 (rand-int 10))
false
user> (> 0.2 (rand))
true
user> (> 0.2 (rand))
(defn factor-5 [x]
(if (and (number? x) (zero? (rem x 1)))
(if (zero? (rand-int 5))
"Boom"
x)))
This returns the required value rather than printing it.
It tests that its argument is numeric, and - if so - that it is a
whole number value, which could be byte, short, int, ... .
(rand-int 5) chooses randomly from 0, 1, ... 4.

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))
)
)
)

Why am I getting a cast error when trying to use Simpson's rule in Clojure?

I'm trying to work through some of the exercises in SICP using Clojure, but am getting an error with my current method of executing Simpson's rule (ex. 1-29). Does this have to do with lazy/eager evalution? Any ideas on how to fix this? Error and code are below:
java.lang.ClassCastException: user$simpson$h__1445 cannot be cast to java.lang.Number
at clojure.lang.Numbers.divide (Numbers.java:139)
Here is the code:
(defn simpson [f a b n]
(defn h [] (/ (- b a) n))
(defn simpson-term [k]
(defn y [] (f (+ a (* k h))))
(cond
(= k 0) y
(= k n) y
(even? k) (* 2 y)
:else (* 4 y)))
(* (/ h 3)
(sum simpson-term 0 inc n)))
You define h as a function of no arguments, and then try to use it as though it were a number. I'm also not sure what you're getting at with (sum simpson-term 0 inc n); I'll just assume that sum is some magic you got from SICP and that the arguments you're passing to it are right (I vaguely recall them defining a generic sum of some kind).
The other thing is, it's almost always a terrible idea to have a def or defn nested within a defn. You probably want either let (for something temporary or local) or another top-level defn.
Bearing in mind that I haven't written a simpson function for years, and haven't inspected this one for algorithmic correctness at all, here's a sketch that is closer to the "right shape" than yours:
(defn simpson [f a b n]
(let [h (/ (- b a) n)
simpson-term (fn [k]
(let [y (f (+ a (* k h)))]
(cond
(= k 0) y
(= k n) y
(even? k) (* 2 y)
:else (* 4 y))))]
(* (/ h 3)
(sum simpson-term 0 inc n))))