Perfect numbers: Difference between revisions

Content added Content deleted
(→‎Functional (faster version): Updated primitives, tidied.)
Line 2,330: Line 2,330:




Or, about 20X faster, as measured by ''time.time()'':
Or, an order of magnitude faster (by restricting the search space):


<lang python>from itertools import (chain)
<lang python>'''Perfect numbers'''
from math import (sqrt)


from itertools import chain

from math import sqrt
# main :: IO ()
def main():
print(
list(filter(perfect, enumFromTo(1)(10000)))
)




# perfect :: Int - > Bool
# perfect :: Int - > Bool
def perfect(n):
def perfect(n):
'''Is n the sum of its proper divisors other than 1 ?'''
lows = list(filter(

lambda x: 0 == (n % x),
# p :: Int -> Bool
enumFromTo(1)(int(sqrt(n)))
))
def p(x):
return (1 < n) and(
'Factor of n.'
n == sum(
return 0 == (n % x)

lows + concatMap(
lambda x: (
# f :: Int -> [Int]
def f(x):
lambda y=(n / x): [y] if x != y else []
)()
'''x -> [] if x is the square root of n,
)(lows)
otherwise x -> [cofactor of x]'''
) / 2
y = n / x
return [y] if x != y else []

lows = list(filter(p, enumFromTo(1)(int(sqrt(n)))))
return 1 < n and (
n == sum(lows + concatMap(f)(lows)) / 2
)


# main :: IO ()
def main():
'''Test'''
print(
list(filter(
perfect,
enumFromTo(1)(10000)
))
)
)




# GENERIC --------------------------------
# GENERIC -------------------------------------------------


# concatMap :: (a -> [b]) -> [a] -> [b]
# concatMap :: (a -> [b]) -> [a] -> [b]
def concatMap(f):
def concatMap(f):
'''Concatenated list over which a function has been mapped.
The list monad can be derived by using a function f which
wraps its output a in list
(using an empty list to represent computational failure).'''
return lambda xs: list(
return lambda xs: list(
chain.from_iterable(
chain.from_iterable(
Line 2,371: Line 2,386:




# enumFromTo :: Int -> Int -> [Int]
# enumFromTo :: (Int, Int) -> [Int]
def enumFromTo(m):
def enumFromTo(m):
'''Integer enumeration from m to n.'''
return lambda n: list(range(m, 1 + n))
return lambda n: list(range(m, 1 + n))