Sunday, April 21, 2013

Finding Perfect Numbers

"Behoves me keep at utterance. I am perfect"
-- Shakespeare Cymbeline
Act III, Scene I, Line 73

Perfection is rare, one can even say perfection is anti-science.  For with perfection there is nothing more to investigate, nothing to ponder, nothing to study.

Perfect Numbers

In mathematics we have a class of numbers which are called perfect.  These numbers have the property that the some of their proper divisors is equal to them.


We can break this algorithm down into three steps.

Step 1: Find divisors




Given the example of n = 6

In Haskell

filter (\x -> mod 6 x == 0) [1..5]

In F#

[1..5] |> List.filter (fun x -> 6 % x = 0)

Step 2: Sum divisors


Still working with n = 6, we have [1, 2, 3] to sum.

In Haskell

sum [1, 2, 3]

In F#

[1; 2; 3] |> List.sum

Step 3: Compare


In Haskell

6 == 6

In F#

6 = 6

Putting it together

In Haskell (on codepad)

isPerfect :: Int -> Bool
isPerfect n =
  sum (
    filter (\x -> mod n x == 0) [1..(n-1)]) == n

main = print $ isPerfect 496

> true

In F# (on tryfsharp)

let isPerfect n =
  let d = [1..(n-1)] 
            |> List.filter (fun x -> n % x = 0)
            |> List.sum
  d = n
;;

isPerfect 496;;

> true