A sparkline is a graph of successive values laid out horizontally
where the height of the line is proportional to the values in succession.



Task

Use the following series of Unicode characters to create a program
that takes a series of numbers separated by one or more whitespace or comma characters
and generates a sparkline-type bar graph of the values on a single line of output.

The eight characters: '▁▂▃▄▅▆▇█'

(Unicode values U+2581 through U+2588).

Use your program to show sparklines for the following input,
here on this page:

 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 
(note the mix of separators in this second case)!
Notes
 
 A space is not part of the generated sparkline.
 The sparkline may be accompanied by simple statistics of the data such as its range.
 A suggestion emerging in later discussion (see Discussion page) is that the bounds between bins should ideally be set to yield the following results for two particular edge cases:
 "0, 1, 19, 20" -> ▁▁██
 (Aiming to use just two spark levels)
 "0, 999, 4000, 4999, 7000, 7999" -> ▁▁▅▅██
 (Aiming to use just three spark levels)
 It may be helpful to include these cases in output tests.
 You may find that the unicode sparklines on this page are rendered less noisily by Google Chrome than by Firefox or Safari.


{
  variables:
  s: sign (1 or -1)
  u: current number
  f: current number fraction length
  v: current number is valid
  t: number of numbers read
  x: biggest fraction
  y: smallest number (without fraction)
  z: biggest number (without fraction)
}
 
{function a: test if top is 0-9, without popping the value, codes 48-57 are in range}
[$$47>\57>~&]a:
 
{function b: test if top is ',' or ' ', without popping the value}
[$$',=\' =|]b:
 
{function c: read a number from the input, given that the first character of the input is already on the stack}
[
  1s:0u:0f:0v: {reset values}
 
  $'-=[1_s:%^]? {if (it is negative) set the sign value to -1 move to next}
  [a;!][48-u;10*+u:1_v:^]# {while (isnumber) do number = number * 10 + decimal and set valid number and move to next}
  $'.=[ {if (it is a decimal) move forward and read fraction}
    %^
    [a;!][48-u;10*+u:f;1+f:1_v:^]# {while (isnumber) do number = number * 10 + decimal and increase fraction length and set valid number and move to next}
  ]?
  $$'-=\'.=|[0v:]? {if next charachter is a '-' or a '.', set invalid}
]c:
 
{function d: normalize number/fraction from stack to max fraction and push that number}
[
  [$x;=~][1+\10*\]# {while (fraction != max) fraction + 1, value * 10}
  % {pop fraction}
]d:
 
0t:
0x:
1_v: { nothing read, so we are still valid }
^[b;!][%^]# {read away any initial separators}
[$1_=~v;&][ {while input != -1 and valid input, leaving input on the stack}
  c;! {read a number}
  t;1+t:u;s;*f;@ {increase count, push number * sign and fraction length onto the stack and bring input back up}
  f;x;>[f;x:]? {set fraction to biggest of current and previous biggest}
  [b;!][%^]# {while (isseparator) move forward}
]#
v;~["error at charachter ",]? {if invalid number, tell them when}
v;[ {if last number also valid, do the math}
  %        {pop the -1}
  t;2*1-q: {var q: points to next value}
  0p:      {var p: whether min/max have been set}
  [q;1+t;>][ {while q + 1 > t}
    q;ø        {current number}
    q;ø        {current fraction}
    d;!        {normalize}
    p;[$y;\>[$y:]? $z;>[$z:]?]?      {compare min/max}
    p;~[1_p:$y:$z:]?     {if (first)) set min/max}
    q;1-q:     {move pointer}
  ]#
 
  t;q: {point q to first value}
  [q;0>][ {while q > 0}
    q;1-øy;-7*z;y;-/ {(number - minvalue) * 7 / (maxvalue - minvalue), should result in 0..7}
    9601+,           {print character}
    q;1-q:           {move pointer}
  ]#
]?