Sparkline in unicode: Difference between revisions

Content added Content deleted
(→‎{{header|Haskell}}: Tidied, pruned out one import.)
(→‎{{header|Python}}: Tidied, updated primitives.)
Line 1,868: Line 1,868:
If the search result is 'not found' (Nothing), then we use the highest (nominally 8th, or index 7) block.
If the search result is 'not found' (Nothing), then we use the highest (nominally 8th, or index 7) block.


<lang python>import re
<lang python>'''Sparkline in Unicode'''


from functools import reduce
import re

# ------------------- LABELLED SPARKLINE -------------------


# sparkLine :: [Float] -> [String]
# sparkLine :: [Float] -> [String]


def sparkLine(xs):
def sparkLine(xs):
'''Unicode sparkline summary of a
list of floating point numbers.
'''
def go(xs):
def go(xs):
ys = sorted(xs)
ys = sorted(xs)
Line 1,880: Line 1,889:
w = (mx - mn) / 8
w = (mx - mn) / 8
lbounds = list(map(lambda i: mn + (w * i), range(1, 8)))
lbounds = list(map(lambda i: mn + (w * i), range(1, 8)))

def spark(x):
def go(i):
return '▁▂▃▄▅▆▇'[i]
return maybe('█')(go)(
findIndex(lambda b: b > x)(lbounds)
)
return [
return [
''.join(map(
''.join(map(spark, xs)),
lambda x: maybe('█')(
lambda i: '▁▂▃▄▅▆▇'[i]
)(findIndex(lambda b: b > x)(lbounds)),
xs
)),
' '.join(map(str, xs)),
' '.join(map(str, xs)),
'\t'.join([
'\t'.join([
Line 1,903: Line 1,914:




# -------------------------- TEST --------------------------
# main :: IO ()
# main :: IO ()
def main():
def main():
'''Tested on some sample lists.
'''
print(
print(
unlines(map(
unlines(map(
compose(compose(unlines)(sparkLine))(readFloats),
compose(compose(unlines, sparkLine), readFloats),
[
[
"0, 1, 19, 20",
"0, 1, 19, 20",
Line 1,918: Line 1,932:




# GENERIC -------------------------------------------------
# ------------------------ GENERIC -------------------------



# Just :: a -> Maybe a
# Just :: a -> Maybe a
def Just(x):
def Just(x):
'''Constructor for an inhabited Maybe (option type) value.
Wrapper containing the result of a computation.
'''
return {'type': 'Maybe', 'Nothing': False, 'Just': x}
return {'type': 'Maybe', 'Nothing': False, 'Just': x}


Line 1,928: Line 1,944:
# Nothing :: Maybe a
# Nothing :: Maybe a
def Nothing():
def Nothing():
'''Constructor for an empty Maybe (option type) value.
Empty wrapper returned where a computation is not possible.
'''
return {'type': 'Maybe', 'Nothing': True}
return {'type': 'Maybe', 'Nothing': True}




# compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
# compose :: ((a -> a), ...) -> (a -> a)
def compose(g):
def compose(*fs):
'''Composition, from right to left,
return lambda f: lambda x: g(f(x))
of a series of functions.
'''
def go(f, g):
def fg(x):
return f(g(x))
return fg
return reduce(go, fs, lambda x: x)




# even :: Int -> Bool
# even :: Int -> Bool
def even(x):
def even(x):
'''True if x is an integer
multiple of two.
'''
return 0 == x % 2
return 0 == x % 2


Line 1,943: Line 1,972:
# findIndex :: (a -> Bool) -> [a] -> Maybe Int
# findIndex :: (a -> Bool) -> [a] -> Maybe Int
def findIndex(p):
def findIndex(p):
'''Just the first index at which an
element in xs matches p,
or Nothing if no elements match.
'''
def go(xs):
def go(xs):
try:
try:
Line 1,950: Line 1,983:
except StopIteration:
except StopIteration:
return Nothing()
return Nothing()
return lambda xs: go(xs)
return go




# maybe :: b -> (a -> b) -> Maybe a -> b
# maybe :: b -> (a -> b) -> Maybe a -> b
def maybe(v):
def maybe(v):
return lambda f: lambda m: v if m.get('Nothing') else (
'''Either the default value v, if m is Nothing,
or the application of f to x,
f(m.get('Just'))
where m is Just(x).
)
'''
return lambda f: lambda m: v if (
None is m or m.get('Nothing')
) else f(m.get('Just'))




# mean :: [Num] -> Float
# mean :: [Num] -> Float
def mean(xs):
def mean(xs):
'''The arithmetic mean of the numeric
values in xs.
'''
return sum(xs) / float(len(xs))
return sum(xs) / float(len(xs))


Line 1,967: Line 2,007:
# readFloats :: String -> [Float]
# readFloats :: String -> [Float]
def readFloats(s):
def readFloats(s):
'''A list of floats parsed from
a numeric string delimited by
commas and/or white space.
'''
return list(map(
return list(map(
float,
float,
re.split('[\s,]+', s)
re.split(r'[\s,]+', s)
))
))


Line 1,975: Line 2,019:
# unlines :: [String] -> String
# unlines :: [String] -> String
def unlines(xs):
def unlines(xs):
'''A single string formed by the intercalation
of a list of strings with the newline character.
'''
return '\n'.join(xs)
return '\n'.join(xs)