114 lines
2.4 KiB
Python
114 lines
2.4 KiB
Python
import re
|
|
|
|
|
|
# sparkLine :: [Float] -> [String]
|
|
def sparkLine(xs):
|
|
def go(xs):
|
|
ys = sorted(xs)
|
|
mn, mx = ys[0], ys[-1]
|
|
n = len(xs)
|
|
mid = n // 2
|
|
w = (mx - mn) / 8
|
|
lbounds = list(map(lambda i: mn + (w * i), range(1, 8)))
|
|
return [
|
|
''.join(map(
|
|
lambda x: maybe('█')(
|
|
lambda i: '▁▂▃▄▅▆▇'[i]
|
|
)(findIndex(lambda b: b > x)(lbounds)),
|
|
xs
|
|
)),
|
|
' '.join(map(str, xs)),
|
|
'\t'.join([
|
|
'Min ' + str(mn),
|
|
'Mean ' + str(round(mean(xs), 2)),
|
|
'Median ' + str(
|
|
(ys[mid - 1] + ys[mid]) / 2 if even(n) else (
|
|
ys[mid]
|
|
)
|
|
),
|
|
'Max ' + str(mx)
|
|
]),
|
|
''
|
|
]
|
|
return go(xs) if xs else []
|
|
|
|
|
|
# main :: IO ()
|
|
def main():
|
|
print(
|
|
unlines(map(
|
|
compose(compose(unlines)(sparkLine))(readFloats),
|
|
[
|
|
"0, 1, 19, 20",
|
|
"0, 999, 4000, 4999, 7000, 7999",
|
|
"1 2 3 4 5 6 7 8 7 6 5 4 3 2 1",
|
|
"1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5"
|
|
]
|
|
))
|
|
)
|
|
|
|
|
|
# GENERIC -------------------------------------------------
|
|
|
|
|
|
# Just :: a -> Maybe a
|
|
def Just(x):
|
|
return {'type': 'Maybe', 'Nothing': False, 'Just': x}
|
|
|
|
|
|
# Nothing :: Maybe a
|
|
def Nothing():
|
|
return {'type': 'Maybe', 'Nothing': True}
|
|
|
|
|
|
# compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
|
|
def compose(g):
|
|
return lambda f: lambda x: g(f(x))
|
|
|
|
|
|
# even :: Int -> Bool
|
|
def even(x):
|
|
return 0 == x % 2
|
|
|
|
|
|
# findIndex :: (a -> Bool) -> [a] -> Maybe Int
|
|
def findIndex(p):
|
|
def go(xs):
|
|
try:
|
|
return Just(next(
|
|
i for i, v in enumerate(xs) if p(v)
|
|
))
|
|
except StopIteration:
|
|
return Nothing()
|
|
return lambda xs: go(xs)
|
|
|
|
|
|
# maybe :: b -> (a -> b) -> Maybe a -> b
|
|
def maybe(v):
|
|
return lambda f: lambda m: v if m.get('Nothing') else (
|
|
f(m.get('Just'))
|
|
)
|
|
|
|
|
|
# mean :: [Num] -> Float
|
|
def mean(xs):
|
|
return sum(xs) / float(len(xs))
|
|
|
|
|
|
# readFloats :: String -> [Float]
|
|
def readFloats(s):
|
|
return list(map(
|
|
float,
|
|
re.split('[\s,]+', s)
|
|
))
|
|
|
|
|
|
# unlines :: [String] -> String
|
|
def unlines(xs):
|
|
return '\n'.join(xs)
|
|
|
|
|
|
# TEST -------------------------------------------------
|
|
if __name__ == '__main__':
|
|
main()
|