RosettaCodeData/Task/Left-factorials/Python/left-factorials-2.py

96 lines
2.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Left factorials"""
from itertools import (accumulate, chain, count, islice)
from operator import (mul, add)
# leftFact :: [Integer]
def leftFact():
'''Left factorial series defined in terms of the factorial series'''
return scanl(add)(0)(
fact()
)
# fact :: [Integer]
def fact():
'''Factorial series a non-finite list'''
return scanl(mul)(1)(
enumFrom(1)
)
# TEST ----------------------------------------------------
# main :: IO ()
def main():
'''Tests'''
print(
'Terms 0 thru 10 inclusive:\n %r'
% take(11)(leftFact())
)
print('\nTerms 20 thru 110 (inclusive) by tens:')
for x in takeFromThenTo(20)(30)(110)(leftFact()):
print(x)
print(
'\n\nDigit counts for terms 1k through 10k (inclusive) by k:\n %r'
% list(map(
compose(len)(str),
takeFromThenTo(1000)(2000)(10000)(
leftFact()
)
))
)
# GENERIC -------------------------------------------------
# compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
def compose(g):
'''Function composition.'''
return lambda f: lambda x: g(f(x))
# enumFrom :: Enum a => a -> [a]
def enumFrom(x):
'''A non-finite stream of enumerable values,
starting from the given value.'''
return count(x) if isinstance(x, int) else (
map(chr, count(ord(x)))
)
# scanl :: (b -> a -> b) -> b -> [a] -> [b]
def scanl(f):
'''scanl is like reduce, but returns a succession of
intermediate values, building from the left.'''
return lambda a: lambda xs: (
accumulate(chain([a], xs), f)
)
# take :: Int -> [a] -> [a]
# take :: Int -> String -> String
def take(n):
'''The prefix of xs of length n,
or xs itself if n > length xs'''
return lambda xs: (
xs[0:n]
if isinstance(xs, list)
else list(islice(xs, n))
)
# takeFromThenTo :: Int -> Int -> Int -> [a] -> [a]
def takeFromThenTo(a):
'''Values drawn from a series betweens positions a and b
at intervals of size z'''
return lambda b: lambda z: lambda xs: islice(
xs, a, 1 + z, b - a
)
if __name__ == '__main__':
main()