Today I am starting my Clojure series in this blog. From now on I will occasionally take a problem and implement it in Clojure for then describing to you how my solutions works.
Today I've came up with a functional solution in Clojure to calculate perfect numbers (which I also posted on Rosetta Code). [...] a perfect number is a positive integer that is equal to the sum of its proper positive divisors, that is, the sum of its positive divisors excluding the number itself [...] (Wikipedia 01.07.2016). But let's have a look at the solution (of which I am quite proud of by the way):
(defn perfect? [n] (= (reduce + (filter #(zero? (rem n %)) (range 1 n))) n))
As you may be able to see this is just a function to check whether a number is a perfect number or not. To print out a list of perfect numbers you have to call this command (in the REPL or by putting it into a new function):
(doseq [i (range 1 1000000) :when (perfect? i)] (println i))
Today we will be analysing the function
perfect?. As we can see here the basic thing
perfect? does is checking whether its calculation equals the parameter n or not:
(defn perfect? [n] (= CALCULATION n))
This calculation exists of the
reduce function which applies a function, in this case
+ to each element in a list. That means that we add all elements in the list that is being created by
(filter #(zero? (rem n %)) (range 1 n)) together.
filter function creates a lazy sequence of all items in a list for which the given predicate is true. In this case
#(zero? (rem n %)) is the predicate and it is being tested for true for all entries in
(range 1 n) (a list from 1 to n-1). In English you could say the whole block like: "Create a list of all numbers from 1 to n which do not produce a remainder when being divided by n."
Now we have the list of all divisors of n except itself. All values of this list are being added using the
reduce function. After checking whether the result is equal n you know whether n is a perfect number or not. Till then,