I've been looking into perfect numbers, and I found this interesting bit of code on rosettacode:
perfect n = n == sum [i | i <- [1..n-1], n `mod` i == 0]
Now, I understand what a perfect number is, and I know which numbers are considered perfect, however I'm struggling to work out which parts of this code do what.
I understand that it's working out the factors of the inputted number, and combining them together to see if it matches the input itself, but I'm not sure how it's doing this.
If anyone could possibly break down this bit of code in a beginner-friendly manner I'd be very appreciative.
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^^^^^^^
For i
from 1
to n-1
(that is, [1, 2, 3, 4 ... n-1]
)
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^^^^
And only for those values where i
evenly divides n
. Discarding values that do not match this requirement.
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^
Include i
in the result list.
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^^
Add the elements of this list together.
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^^
And return True
iff the total equals n
.
[i | i <- [1..n-1], n `mod` i == 0]
Starting from the middle, you can read it like this: for each element i
of the [1..n-1]
list, check if n `mod` i
equals 0
. If it does, include i
in the result list (that's the part to the left of the |
. Without using the list comprehension syntax, that might be written using the filter
function:
filter (\i -> n `mod` i == 0)
The elements of the resulting list are then added with sum
, and, finally, the sum is tested for equality with n
.