Testing if an inputted Int is a perfect number

2020-05-03 09:53发布

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.

2条回答
再贱就再见
2楼-- · 2020-05-03 10:21
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.

查看更多
家丑人穷心不美
3楼-- · 2020-05-03 10:36
[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.

查看更多
登录 后发表回答