RosettaCodeData/Task/Digital-root/Python/digital-root-2.py

65 lines
1.4 KiB
Python

from functools import (reduce)
# main :: IO ()
def main():
print (
tabulated(digitalRoot)(
'Integer -> (additive persistence, digital root):'
)([627615, 39390, 588225, 393900588225, 55])
)
# digitalRoot :: Int -> (Int, Int)
def digitalRoot(n):
'''Integer -> (additive persistence, digital root)'''
# f :: (Int, Int) -> (Int, Int)
def f(pn):
p, n = pn
return (
1 + p,
reduce(lambda a, x: a + int(x), str(n), 0)
)
# p :: (Int , Int) -> Bool
def p(pn):
return 10 > pn[1]
return until(p)(f)(
(0, abs(int(n)))
)
# GENERIC -------------------------------------------------
# compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
def compose(g):
return lambda f: lambda x: g(f(x))
# tabulated :: (a -> b) -> String -> String
def tabulated(f):
'''function -> heading -> input List -> tabulated output string'''
def go(s, xs):
fw = compose(len)(str)
w = fw(max(xs, key=fw))
return s + '\n' + '\n'.join(list(map(
lambda x: str(x).rjust(w, ' ') + ' -> ' + str(f(x)), xs
)))
return lambda s: lambda xs: go(s, xs)
# until :: (a -> Bool) -> (a -> a) -> a -> a
def until(p):
def go(f, x):
v = x
while not p(v):
v = f(v)
return v
return lambda f: lambda x: go(f, x)
if __name__ == '__main__':
main()