RosettaCodeData/Task/Convert-seconds-to-compound.../Python/convert-seconds-to-compound...

88 lines
2.3 KiB
Python

'''Compound duration'''
from functools import reduce
from itertools import chain
# compoundDurationFromUnits :: [Num] -> [String] -> Num -> [(Num, String)]
def compoundDurationFromUnits(qs):
'''A list of compound string representions of a number n of time units,
in terms of the multiples given in qs, and the labels given in ks.
'''
return lambda ks: lambda n: list(
chain.from_iterable(map(
lambda v, k: [(v, k)] if 0 < v else [],
mapAccumR(
lambda a, x: divmod(a, x) if 0 < x else (1, a)
)(n)(qs)[1],
ks
))
)
# --------------------------TEST---------------------------
# main :: IO ()
def main():
'''Tests of various durations, with a
particular set of units and labels.
'''
print(
fTable('Compound durations from numbers of seconds:\n')(str)(
quoted("'")
)(
lambda n: ', '.join([
str(v) + ' ' + k for v, k in
compoundDurationFromUnits([0, 7, 24, 60, 60])(
['wk', 'd', 'hr', 'min', 'sec']
)(n)
])
)([7259, 86400, 6000000])
)
# -------------------------GENERIC-------------------------
# fTable :: String -> (a -> String) ->
# (b -> String) -> (a -> b) -> [a] -> String
def fTable(s):
'''Heading -> x display function -> fx display function ->
f -> xs -> tabular string.
'''
def go(xShow, fxShow, f, xs):
ys = [xShow(x) for x in xs]
w = max(map(len, ys))
return s + '\n' + '\n'.join(map(
lambda x, y: y.rjust(w, ' ') + ' -> ' + fxShow(f(x)),
xs, ys
))
return lambda xShow: lambda fxShow: lambda f: lambda xs: go(
xShow, fxShow, f, xs
)
# mapAccumR :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
def mapAccumR(f):
'''A tuple of an accumulation and a list derived by a combined
map and fold, with accumulation from right to left.
'''
def go(a, x):
acc, y = f(a[0], x)
return (acc, [y] + a[1])
return lambda acc: lambda xs: (
reduce(go, reversed(xs), (acc, []))
)
# quoted :: Char -> String -> String
def quoted(c):
'''A string flanked on both sides
by a specified quote character.
'''
return lambda s: c + s + c
# MAIN ---
if __name__ == '__main__':
main()