88 lines
2.3 KiB
Python
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()
|