Sparkline in unicode: Difference between revisions

m
m (→‎{{header|Wren}}: Minor tidy)
 
(83 intermediate revisions by 25 users not shown)
Line 10:
and generates a sparkline-type bar graph of the values on a single line of output.
 
The eight characters: <code>'▁▂▃▄▅▆▇█'</code><br>
(Unicode values U+2581 through U+2588).
 
Line 22:
* 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 [[Talk:Sparkline_in_unicode|Discussion]] page) is that the bounds between bins should ideally be set to yield the following results for two particular edge cases:
 
:: <code>"0, 1, 19, 20" -> ▁▁██</code>
:: (Aiming to use just two spark levels)
 
:: <code>"0, 999, 4000, 4999, 7000, 7999" -> ▁▁▅▅██</code>
:: (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.
<br><br>
 
=={{header|APL}}==
Note → this is in a 0-indexed version of APL
'''Solution''':<langsyntaxhighlight APLlang="apl"> sparkln←{'▁▂▃▄▅▆▇█'[⌊0.5+7×⍵÷⌈/⍵]}</langsyntaxhighlight>
'''Example''':<langsyntaxhighlight APLlang="apl"> sparkln 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
▂▃▄▅▅▆▇█▇▆▅▅▄▃▂
sparkln 1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5
▂▁▄▃▆▅█▇
</syntaxhighlight>
</lang>
Note → APL accepts the input with commas and spaces naturally. If one wanted to read input as a string they could use ⍎⍞ to do so.
 
 
=={{header|AppleScript}}==
<syntaxhighlight lang="applescript">use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
 
on run
unlines(map(¬
compose(compose(unlines, sparkLine), readFloats), ¬
{"0, 1, 19, 20", "0, 999, 4000, 4999, 7000, 7999", ¬
"0, 1000, 4000, 5000, 7000, 8000", ¬
"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"}))
end run
 
 
-- sparkLine :: [Float] -> [String]
<lang AppleScript>use framework "Foundation" -- Yosemite onwards – for splitting by regex
 
-- sparkLine :: [Num] -> String
on sparkLine(xs)
set minys to minimumBysort(my numericOrdering, xs)
set maxmn to maximumBy(myitem numericOrdering,1 xs)of ys
set dataRangemx to maxitem -1 minof ys
set n to length of xs
set mid to (n div 2)
set w to (mx - mn) / 8
script bound
-- scale :: Num -> Num
script scale on |λ|(x)
on lambda mn + (w * x)
end ((x - min) * 7) / dataRange|λ|
end lambda
end script
set lbounds to map(bound, enumFromTo(1, 7))
script spark
-- bucket :: Num -> String
script bucket on |λ|(x)
on lambda(n) script flipGT
if n 0 andon n < 8 then|λ|(b)
item (n + 1 asb integer)> of "▁▂▃▄▅▆▇█"x
else end |λ|
end missing valuescript
endscript ifindexedBlock
end lambda on |λ|(i)
item i of "▁▂▃▄▅▆▇"
end |λ|
end script
maybe("█", indexedBlock, findIndex(flipGT, lbounds))
end |λ|
end script
script str
intercalate("", map(bucket, map(scale, xs)))
on |λ|(x)
x as string
end |λ|
end script
{concat(map(spark, xs)), ¬
unwords(map(str, xs)), ¬
"Min " & mn as string, ¬
"Mean " & roundTo(mean(xs), 2) as string, ¬
"Median " & bool(item mid of xs, ((item mid of xs) + ¬
(item (mid + 1) of xs)) / 2, even(n)), ¬
"Max " & mx as string, ""}
end sparkLine
 
 
-- numericOrdering :: Num -> Num -> (-1 | 0 | 1)
-- GENERIC -------------------------------------------------
on numericOrdering(a, b)
 
if a < b then
-- Just :: a -> Maybe -1a
on Just(x)
{type:"Maybe", Nothing:false, Just:x}
end Just
 
-- Nothing :: Maybe a
on Nothing()
{type:"Maybe", Nothing:true}
end Nothing
 
-- bool :: a -> a -> Bool -> a
on bool(f, t, p)
if p then
t
else
if a > b thenf
1
else
0
end if
end if
end numericOrderingbool
 
-- compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
 
on compose(f, g)
-- TEST
script
on run
property mf : mReturn(f)
property mg : mReturn(g)
-- splitNumbers :: String -> [Real]
script splitNumbers on |λ|(x)
script asReal mf's |λ|(mg's |λ|(x))
end on lambda(x)|λ|
x as real
end lambda
end script
on lambda(s)
map(asReal, splitRegex("[\\s,]+", s))
end lambda
end script
end compose
map(sparkLine, map(splitNumbers, ["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", ¬
"3 2 1 0 -1 -2 -3 -4 -3 -2 -1 0 1 2 3", ¬
"-1000 100 1000 500 200 -400 -700 621 -189 3"]))
-- {"▁▂▃▄▅▆▇█▇▆▅▄▃▂▁","▂▁▄▃▆▅█▇","█▇▆▅▄▃▂▁▂▃▄▅▆▇█","▁▅█▆▅▃▂▇▄▅"}
end run
 
-- concat :: [[a]] -> [a]
-- concat :: [String] -> String
on concat(xs)
set lng to length of xs
if 0 < lng and string is class of (item 1 of xs) then
set acc to ""
else
set acc to {}
end if
repeat with i from 1 to lng
set acc to acc & item i of xs
end repeat
acc
end concat
 
-- enumFromTo :: Int -> Int -> [Int]
on enumFromTo(m, n)
if m ≤ n then
set lst to {}
repeat with i from m to n
set end of lst to i
end repeat
return lst
else
return {}
end if
end enumFromTo
 
-- even :: Int -> Bool
on even(x)
0 = x mod 2
end even
 
-- Takes a predicate function and a list and
-- GENERIC LIBRARY FUNCTIONS
-- returns Just( the 1-based index of the first
-- element ) in the list satisfying the predicate
-- or Nothing if there is no such element.
-- findIndex(isSpace, "hello world")
--> {type:"Maybe", Nothing:false, Just:6}
 
-- findIndex(even, [3, 5, 7, 8, 9])
--> {type:"Maybe", Nothing:false, Just:4}
 
-- findIndex(isUpper, "all lower case")
--> {type:"Maybe", Nothing:true}
-- findIndex :: (a -> Bool) -> [a] -> Maybe Int
on findIndex(p, xs)
tell mReturn(p)
set lng to length of xs
repeat with i from 1 to lng
if |λ|(item i of xs) then return Just(i)
end repeat
return Nothing()
end tell
end findIndex
 
-- foldl :: (a -> b -> a) -> a -> [b] -> a
Line 117 ⟶ 201:
set lng to length of xs
repeat with i from 1 to lng
set v to lambda|λ|(v, item i of xs, i, xs)
end repeat
return v
Line 129 ⟶ 213:
set lst to {}
repeat with i from 1 to lng
set end of lst to lambda|λ|(item i of xs, i, xs)
end repeat
return lst
Line 135 ⟶ 219:
end map
 
-- maximumBymean :: (a -> a -> Ordering) -> [aNum] -> a Num
on maximumBymean(f, xs)
script max
propertyon cmp|λ|(a, : fx)
on lambda( a, b)+ x
end |λ|
if a is missing value or cmp(a, b) < 0 then
b
else
a
end if
end lambda
end script
foldl(result, 0, xs) / (length of xs)
end mean
foldl(max, missing value, xs)
end maximumBy
 
-- | The 'maybe' function takes a default value, a function, and a 'Maybe'
-- minimumBy :: (a -> a -> Ordering) -> [a] -> a
-- value. If the 'Maybe' value is 'Nothing', the function returns the
on minimumBy(f, xs)
-- default value. Otherwise, it applies the function to the value inside
script min
-- the 'Just' and returns the result.
property cmp : f
-- maybe :: b -> (a -> b) on-> Maybe lambda(a, -> b)
on maybe(v, f, mb)
if a is missing value or cmp(a, b) > 0 then
if Nothing of mb bthen
elsev
aelse
tell mReturn(f) to |λ|(Just endof ifmb)
end lambdaif
end maybe
 
-- Lift 2nd class handler function into 1s class script wrapper
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
if script is class of f then
f
else
script
property |λ| : f
end script
end if
end mReturn
 
-- readFloats :: String -> [Float]
on readFloats(s)
script asReal
on |λ|(n)
n as real
end |λ|
end script
map(asReal, splitRegex("[\\s,]+", s))
end readFloats
 
-- regexMatches :: String -> String -> [[String]]
on regexMatches(strRegex, strHay)
set ca to current application
-- NSNotFound handling and and High Sierra workaround due to @sl1974
set NSNotFound to a reference to 9.22337203685477E+18 + 5807
set oRgx to ca's NSRegularExpression's regularExpressionWithPattern:strRegex ¬
options:((ca's NSRegularExpressionAnchorsMatchLines as integer)) ¬
|error|:(missing value)
set oString to ca's NSString's stringWithString:strHay
script matchString
foldl(min, missing value, xs)
on |λ|(m)
end minimumBy
script rangeMatched
on |λ|(i)
tell (m's rangeAtIndex:i)
set intFrom to its location
if NSNotFound ≠ intFrom then
text (intFrom + 1) thru (intFrom + (its |length|)) of strHay
else
missing value
end if
end tell
end |λ|
end script
end |λ|
end script
script asRange
on |λ|(x)
range() of x
end |λ|
end script
map(asRange, (oRgx's matchesInString:oString ¬
options:0 range:{location:0, |length|:oString's |length|()}) as list)
end regexMatches
 
 
-- roundTo :: Float -> Int -> Float
on roundTo(x, n)
set d to 10 ^ n
(round (x * d)) / d
end roundTo
 
-- sort :: Ord a => [a] -> [a]
on sort(xs)
((current application's NSArray's arrayWithArray:xs)'s ¬
sortedArrayUsingSelector:"compare:") as list
end sort
 
-- splitRegex :: RegexPatternRegex -> String -> [String]
on splitRegex(strRegex, str)
set lstMatches to regexMatches(strRegex, str)
if length of lstMatches > 0 then
script preceding
on lambda|λ|(a, x)
set iFrom to start of a
set iLocn to (location of x)
Line 182 ⟶ 328:
end if
{parts:parts of a & strPart, start:iLocn + (length of x) - 1}
end lambda|λ|
end script
Line 198 ⟶ 344:
end splitRegex
 
-- regexMatchesunlines :: RegexPattern[String] -> String -> [{location:Int, length:Int}]
on unlines(xs)
on regexMatches(strRegex, str)
set ca{dlm, tomy currenttext item delimiters} to application¬
{my text item delimiters, linefeed}
set oRgx to ca's NSRegularExpression's regularExpressionWithPattern:strRegex ¬
set str to xs as text
options:((ca's NSRegularExpressionAnchorsMatchLines as integer)) |error|:(missing value)
set my text item delimiters to dlm
set oString to ca's NSString's stringWithString:str
str
set oMatches to oRgx's matchesInString:oString options:0 range:{location:0, |length|:oString's |length|()}
end unlines
set lstMatches to {}
set lng to count of oMatches
repeat with i from 1 to lng
set end of lstMatches to range() of item i of oMatches
end repeat
lstMatches
end regexMatches
 
-- intercalateunwords :: Text -> [TextString] -> TextString
on unwords(xs)
on intercalate(strText, lstText)
set {dlm, my text item delimiters} to {my text item delimiters, strText}¬
set strJoined to lstText as{my text item delimiters, space}
set s to xs as text
set my text item delimiters to dlm
return strJoineds
end unwords</syntaxhighlight>
end intercalate
{{Out}}
<pre>▁▁██
0.0 1.0 19.0 20.0
Min 0.0
Mean 10.0
Median 10.0
Max 20.0
 
▁▁▅▅██
-- Lift 2nd class handler function into 1st class script wrapper
0.0 999.0 4000.0 4999.0 7000.0 7999.0
-- mReturn :: Handler -> Script
Min 0.0
on mReturn(f)
Mean 4166.17
if class of f is script then
Median 4499.5
f
Max 7999.0
else
script
property lambda : f
end script
end if
end mReturn
</lang>
 
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 7.0 6.0 5.0 4.0 3.0 2.0 1.0
Min 1.0
Mean 4.27
Median 7.0
Max 8.0
 
▂▁▄▃▆▅█▇
1.5 0.5 3.5 2.5 5.5 4.5 7.5 6.5
Min 0.5
Mean 4.0
Median 4.0
Max 7.5</pre>
 
=={{header|Arturo}}==
<pre>{"▁▂▃▄▅▆▇█▇▆▅▄▃▂▁","▂▁▄▃▆▅█▇","█▇▆▅▄▃▂▁▂▃▄▅▆▇█","▁▅█▆▅▃▂▇▄▅"}</pre>
 
<syntaxhighlight lang="rebol">bar: "▁▂▃▄▅▆▇█"
barcount: to :floating dec size bar
 
while ø [
line: input "Numbers separated by spaces: "
numbers: to [:floating] split.words line
mn: min numbers
mx: max numbers
extent: mx-mn
sparkLine: new ""
loop numbers 'n [
i: to :integer barcount*(n-mn)//extent
'sparkLine ++ bar\[i]
]
print ["min:" round.to:1 mn "max:" round.to:1 mx]
print sparkLine
print ""
]</syntaxhighlight>
 
{{out}}
 
<pre>Numbers separated by spaces: 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
min: 1.0 max: 8.0
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
 
Numbers separated by spaces: 1.5 0.5 3.5 2.5 5.5 4.5 7.5 6.5
min: 0.5 max: 7.5
▂▁▄▃▆▅█▇
</pre>
 
=={{header|AutoHotkey}}==
{{works with|AutoHotkey_L}}
<langsyntaxhighlight AutoHotkeylang="autohotkey">SetFormat, FloatFast, 0.1
strings := ["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"]
Line 263 ⟶ 446:
Chars .= Chr(0x2581 + Round(7 * (A_LoopField - Min) / Rng))
return, {"Min": Min, "Max": Max, "Rng": Rng, "Chars": Chars}
}</langsyntaxhighlight>
{{out}}
<pre>Min: 1, Max: 8, Range: 7
Line 270 ⟶ 453:
Min: 0.5, Max: 7.5, Range: 7.0
▂▁▄▃▆▅█▇</pre>
 
=={{header|BASIC}}==
==={{header|VBScript}}===
<syntaxhighlight lang="vb">
'Sparkline
 
sub ensure_cscript()
if instrrev(ucase(WScript.FullName),"WSCRIPT.EXE")then
createobject("wscript.shell").run "CSCRIPT //nologo """ &_
WScript.ScriptFullName &"""" ,,0
wscript.quit
end if
end sub
 
class bargraph
private bar,mn,mx,nn,cnt
 
Private sub class_initialize()
bar=chrw(&h2581)&chrw(&h2582)&chrw(&h2583)&chrw(&h2584)&chrw(&h2585)&_
chrw(&h2586)&chrw(&h2587)&chrw(&h2588)
nn=8
end sub
 
 
public function bg (s)
a=split(replace(replace(s,","," ")," "," ")," ")
 
mn=999999:mx=-999999:cnt=ubound(a)+1
for i=0 to ubound(a)
a(i)=cdbl(trim(a(i)))
if a(i)>mx then mx=a(i)
if a(i)<mn then mn=a(i)
next
ss="Data: "
for i=0 to ubound(a) :ss=ss & right (" "& a(i),6) :next
ss=ss+vbcrlf + "sparkline: "
for i=0 to ubound(a)
x=scale(a(i))
'wscript.echo mn,mx, a(i),x
ss=ss & string(6,mid(bar,x,1))
next
bg=ss &vbcrlf & "min: "&mn & " max: "& mx & _
" cnt: "& ubound(a)+1 &vbcrlf
end function
 
private function scale(x)
if x=<mn then
scale=1
elseif x>=mx then
scale=nn
else
scale=int(nn* (x-mn)/(mx-mn)+1)
end if
end function
 
end class
 
ensure_cscript
 
set b=new bargraph
wscript.stdout.writeblanklines 2
wscript.echo b.bg("1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1")
wscript.echo b.bg("1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5")
wscript.echo b.bg("0, 1, 19, 20")
wscript.echo b.bg("0, 999, 4000, 4999, 7000, 7999")
set b=nothing
 
wscript.echo "If bars don't display correctly please set the the console " & _
"font to DejaVu Sans Mono or any other that has the bargrph characters" & _
vbcrlf
 
wscript.stdout.write "Press any key.." : wscript.stdin.read 1
</syntaxhighlight>
{{out}}
<pre>
 
 
Data: 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
sparkline: ▁▁▁▁▁▁▂▂▂▂▂▂▃▃▃▃▃▃▄▄▄▄▄▄▅▅▅▅▅▅▆▆▆▆▆▆▇▇▇▇▇▇██████▇▇▇▇▇▇▆▆▆▆▆▆▅▅▅▅▅▅▄▄▄▄▄▄▃▃▃▃▃▃▂▂▂▂▂▂▁▁▁▁▁▁
min: 1 max: 8 cnt: 15
 
Data: 15 5 35 25 55 45 75 65
sparkline: ▂▂▂▂▂▂▁▁▁▁▁▁▄▄▄▄▄▄▃▃▃▃▃▃▆▆▆▆▆▆▅▅▅▅▅▅██████▇▇▇▇▇▇
min: 5 max: 75 cnt: 8
 
Data: 0 1 19 20
sparkline: ▁▁▁▁▁▁▁▁▁▁▁▁████████████
min: 0 max: 20 cnt: 4
 
Data: 0 999 4000 4999 7000 7999
sparkline: ▁▁▁▁▁▁▁▁▁▁▁▁▅▅▅▅▅▅▅▅▅▅▅▅████████████
min: 0 max: 7999 cnt: 6
 
If bars don't display correctly please set the the console
font to DejaVu Sans Mono or any other that has the bargrph characters
 
Press any key..
</pre>
 
=={{header|C}}==
This seemingly simple task turns out to be very complicated for languages like C. As the characters to be printed are Unicode, there is no platform independent way to do so. The implementation below works on Linux but not on Windows, detailed investigations show that there is no way, at least no reliable and/or easily reproducible way, to accomplish this task via C on Windows. This is not due to any lacunae in C but due to the vagaries of the Windows Command shell.
===Linux version===
Accepts data via command line, prints out usage on incorrect invocation.
<syntaxhighlight lang="c">
#include<string.h>
#include<stdlib.h>
#include<locale.h>
#include<stdio.h>
#include<wchar.h>
#include<math.h>
 
int main(int argC,char* argV[])
{
double* arr,min,max;
char* str;
int i,len;
if(argC == 1)
printf("Usage : %s <data points separated by spaces or commas>",argV[0]);
else{
arr = (double*)malloc((argC-1)*sizeof(double));
for(i=1;i<argC;i++){
len = strlen(argV[i]);
if(argV[i][len-1]==','){
str = (char*)malloc(len*sizeof(char));
strncpy(str,argV[i],len-1);
arr[i-1] = atof(str);
free(str);
}
else
arr[i-1] = atof(argV[i]);
if(i==1){
min = arr[i-1];
max = arr[i-1];
}
else{
min=(min<arr[i-1]?min:arr[i-1]);
max=(max>arr[i-1]?max:arr[i-1]);
}
}
printf("\n%Max : %lf,Min : %lf,Range : %lf\n",max,min,max-min);
setlocale(LC_ALL, "");
for(i=1;i<argC;i++){
printf("%lc", (wint_t)(9601 + (int)ceil((arr[i-1]-min)/(max-min)*7)));
}
}
return 0;
}
</syntaxhighlight>
Invocation and output :
<pre>
/home/aamrun/rosettaCode>./sparkLine 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
Max : 8.000000,Min : 1.000000,Range : 7.000000
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
/home/aamrun/rosettaCode>./sparkLine 1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5
Max : 7.500000,Min : 0.500000,Range : 7.000000
▂▁▄▃▆▅█▇
</pre>
 
=={{header|C++}}==
 
<lang cpp>#include <iostream>
<syntaxhighlight lang="cpp">
#include <iostream>
#include <sstream>
#include <vector>
Line 339 ⟶ 688:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>Min: 1; Max: 8; Range: 7
Line 347 ⟶ 696:
 
=={{header|Clojure}}==
<langsyntaxhighlight Clojurelang="clojure">(defn sparkline [nums]
(let [sparks "▁▂▃▄▅▆▇█"
high (apply max nums)
Line 361 ⟶ 710:
(recur (read-line)))))
 
(spark (read-line))</langsyntaxhighlight>
 
{{Out}}
Line 370 ⟶ 719:
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">(defun buckets (numbers)
(loop with min = (apply #'min numbers)
with max = (apply #'max numbers)
Line 412 ⟶ 761:
 
(string->sparkline "1 2 3 4 5 6 7 8 7 6 5 4 3 2 1")
(string->sparkline "1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5")</langsyntaxhighlight>
{{out}}
<pre>Min: 1, Max: 8, Range: 7
Line 421 ⟶ 770:
=={{header|D}}==
{{trans|Python}}
<langsyntaxhighlight lang="d">void main() {
import std.stdio, std.range, std.algorithm, std.conv,
std.string, std.regex;
Line 436 ⟶ 785:
immutable div = (mm[1] - mm[0]) / (bars.length - 1);
numbers.map!(n => bars[cast(int)((n - mm[0]) / div)]).writeln;
}</langsyntaxhighlight>
The output is the same as the Python entry
(but it only accepts one series of values at a time).
=={{header|Delphi}}==
<syntaxhighlight lang="delphi">
program Sparkline_in_unicode;
 
{$APPTYPE CONSOLE}
 
//Translated from: https://www.arduino.cc/reference/en/language/functions/math/map/
function map(x, in_min, in_max, out_min, out_max: Double): Double;
begin
Result := ((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min);
end;
 
procedure Normalize(var Values: TArray<Double>; outMin, outMax: Double);
var
i: Integer;
inMax, inMin, value: Double;
begin
if Length(Values) = 0 then
Exit;
 
inMin := Values[0];
inMax := Values[0];
 
for value in Values do
begin
if value > inMax then
inMax := value;
if value < inMin then
inMin := value;
end;
 
for i := 0 to High(Values) do
Values[i] := map(Values[i], inMin, inMax, outMin, outMax);
end;
 
function Sparkline(Values: TArray<Double>): UnicodeString;
var
value: Double;
const
CHARS: UnicodeString = #$2581#$2582#$2583#$2584#$2585#$2586#$2587#$2588;
begin
Result := '';
Normalize(Values, 1, 8);
for value in Values do
Result := Result + CHARS[Trunc(value)];
end;
 
begin
writeln(Sparkline([1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1]));
writeln(Sparkline([1.5, 0.5, 3.5, 2.5, 5.5, 4.5, 7.5, 6.5]));
Readln;
end.
</syntaxhighlight>
=={{header|Elixir}}==
<langsyntaxhighlight lang="elixir">defmodule RC do
def sparkline(str) do
values = str |> String.split(~r/(,| )+/)
Line 448 ⟶ 849:
IO.puts Enum.map(values, &(round((&1 - min) / (max - min) * 7 + 0x2581)))
end
end</langsyntaxhighlight>
Usage:
<syntaxhighlight lang="text">str1 = "1 2 3 4 5 6 7 8 7 6 5 4 3 2 1"
str2 = "1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5"
 
RC.sparkline(str1)
IO.puts "" # newline
RC.sparkline(str2)</langsyntaxhighlight>
{{out}}
<pre>
Line 464 ⟶ 865:
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">open System
open System.Globalization
open System.Text.RegularExpressions
Line 485 ⟶ 886:
|> List.map (fun x -> bars.[int ((x - min)/(max - min) * barsCount)])
|> String.Concat
|> printfn "%s"</langsyntaxhighlight>
{{out}}
<pre>Numbers separated by anything: 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
Line 494 ⟶ 895:
▂▁▄▃▆▅█▇
Numbers separated by anything:
</pre>
 
=={{header|Factor}}==
<syntaxhighlight lang="factor">USING: formatting kernel math math.order math.parser
math.statistics sequences splitting ;
 
: sparkline-index ( v min max -- i )
[ drop - 8 * ] [ swap - /i ] 2bi 0 7 clamp 9601 + ;
 
: (sparkline) ( seq -- new-seq )
dup minmax [ sparkline-index ] 2curry "" map-as ;
 
: sparkline ( str -- new-str )
", " split harvest [ string>number ] map (sparkline) ;
 
{
"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"
"0, 1, 19, 20"
"0, 999, 4000, 4999, 7000, 7999"
} [ dup sparkline "%u -> %s\n" printf ] each</syntaxhighlight>
{{out}}
<pre>
"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" -> ▂▁▄▃▆▅█▇
"0, 1, 19, 20" -> ▁▁██
"0, 999, 4000, 4999, 7000, 7999" -> ▁▁▅▅██
</pre>
 
=={{header|FALSE}}==
<langsyntaxhighlight lang="false">{
variables:
s: sign (1 or -1)
Line 564 ⟶ 992:
q;1-q: {move pointer}
]#
]?</langsyntaxhighlight>
This implementation can only accept one series of numbers at a time.
{{out}}
Line 573 ⟶ 1,001:
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 646 ⟶ 1,074:
}
return
}</langsyntaxhighlight>
{{out}}
<pre>
Line 684 ⟶ 1,112:
 
=={{header|Groovy}}==
<langsyntaxhighlight lang="groovy">def sparkline(List<Number> list) {
def (min, max) = [list.min(), list.max()]
def div = (max - min) / 7
list.collect { (char)(0x2581 + (it-min) * div) }.join()
}
def sparkline(String text) { sparkline(text.split(/[ ,]+/).collect { it as Double }) }</langsyntaxhighlight>
Test Code
<langsyntaxhighlight lang="groovy">["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"].each { dataset ->
println " Dataset: $dataset"
println "Sparkline: ${sparkline(dataset)}"
}</langsyntaxhighlight>
{{out}}
<pre>
Line 704 ⟶ 1,132:
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">import Data.CharList.Split (chrsplitOneOf)
import Data.List.SplitChar (splitOneOfchr)
 
 
toSparkLine :: [Double] -> [Char]
toSparkLine :: [Double] -> String
toSparkLine xs = map cl xs
where
top = maximum xs
bot = minimum xs
range = top - bot
cl x = chr $ 0x2581 + roundfloor (min 7 ((x - bot) / range * 78))
 
makeSparkLine :: String -> (String, Stats)
makeSparkLine xs = (toSparkLine parsed, stats parsed)
where
where parsed = map read $ filter (not . null) $ splitOneOf " ," xs
parsed = map read $ filter (not . null) $ splitOneOf " ," xs
 
data Stats = Stats { minValue, maxValue, rangeOfValues :: Double,
data Stats = Stats
numberOfValues :: Int }
{ minValue, maxValue, rangeOfValues :: Double
, numberOfValues :: Int
}
 
instance Show Stats where
show (Stats mn mx r n) = "min: " ++ show mn ++ "; max: " ++ show mx ++
"min: " ++
"; range: " ++ show r ++ "; no. of values: " ++ show n
show mn ++
"; max: " ++
show mx ++ "; range: " ++ show r ++ "; no. of values: " ++ show n
 
stats :: [Double] -> Stats
stats xs = Stats { minValue = mn, maxValue = mx,
Stats
rangeOfValues = mx - mn, numberOfValues = length xs }
{ minValue where= mn
, mnmaxValue = minimum xsmx
, rangeOfValues = mx = maximum- xsmn
, numberOfValues = length xs
}
where
mn = minimum xs
mx = maximum xs
 
drawSparkLineWithStats :: String -> IO ()
drawSparkLineWithStats xs = putStrLn sp >> print st
where
where (sp, st) = makeSparkLine xs
(sp, st) = makeSparkLine xs
 
main :: IO ()
main =
main = mapM_ drawSparkLineWithStats
mapM_
["1 2 3 4 5 6 7 8 7 6 5 4 3 2 1",
drawSparkLineWithStats
"1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5",
[ "3 2 1 0, -1, -219, -3 -4 -3 -2 -1 0 1 2 320",
, "0, 999, 4000, 4999, 7000, 7999"
"-1000 100 1000 500 200 -400 -700 621 -189 3"]
, "1 2 3 4 5 6 7 8 7 6 5 4 3 2 1"
</lang>
, "1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5"
, "3 2 1 0 -1 -2 -3 -4 -3 -2 -1 0 1 2 3"
, "-1000 100 1000 500 200 -400 -700 621 -189 3"
]</syntaxhighlight>
{{Out}}
<pre>▁▁██
<pre>▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
min: 0.0; max: 20.0; range: 20.0; no. of values: 4
▁▁▅▅██
min: 0.0; max: 7999.0; range: 7999.0; no. of values: 6
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
min: 1.0; max: 8.0; range: 7.0; no. of values: 15
▂▁▄▃▆▅█▇
Line 751 ⟶ 1,200:
█▇▆▅▄▃▂▁▂▃▄▅▆▇█
min: -4.0; max: 3.0; range: 7.0; no. of values: 15
▁▅█▇▅▃▂▇▄▅
▁▅█▆▅▃▂▇▄▅
min: -1000.0; max: 1000.0; range: 2000.0; no. of values: 10</pre>
 
 
Or, stripping back toa the basicslittle:
{{Trans|JavaScriptPython}}
<syntaxhighlight lang ="haskell">import Data.List.SplitBifunctor (splitOneOfbimap)
import Data.List (findIndex)
import Data.List.Split (splitOneOf)
import Data.Maybe (maybe)
 
------------------------ SPARK LINE ----------------------
 
sparkLine :: [Float] -> String
sparkLine xs[] = ""
sparkLine xxs@(x : xs) =
(("▁▂▃▄▅▆▇█" !!) . floor . (/ range) . (7 *) . subtract min) <$> xs
fmap
( maybe '█' ("▁▂▃▄▅▆▇" !!)
. flip findIndex lbounds
. (<)
)
xxs
where
(mn, mx) = foldr (bimap . min <*> max) (x, x) xs
min = minimum xs
rangew = maximum xs(mx - minmn) / 8
lbounds = (mn +) . (w *) <$> [1 .. 7]
 
parseFloats :: String -> [Float]
parseFloats = (read <$>) . filter (not . null) . splitOneOf " ,"
 
--------------------------- TEST -------------------------
main :: IO ()
main =
mapM_ putStrLn $
sparkLine . parseFloats
putStrLn
<$> [ "0, 1, 19, 20",
((sparkLine . parseFloats) <$>
[ "1 2 3 4 5 6 7 8 7 6"0, 5999, 44000, 34999, 27000, 17999",
, "1.5, 0.52 3.5, 2.54 5.5, 4.56 7 8 7.5, 6. 5 4 3 2 1",
, "3 2 1 0 -1 -2 -3"1.5, -40.5 -3.5, -2.5 -15.5, 04.5 17.5, 2 36.5"
]
, "-1000 100 1000 500 200 -400 -700 621 -189 3"
 
])</lang>
parseFloats :: String -> [Float]
parseFloats =
fmap read
. filter (not . null)
. splitOneOf " ,"</syntaxhighlight>
{{Out}}
<pre>▁▁██
<pre>▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
▁▁▅▅██
▂▁▄▃▆▅█▇
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
█▇▆▅▄▃▂▁▂▃▄▅▆▇█
▂▁▄▃▆▅█▇</pre>
▁▄█▆▅▃▂▆▃▄</pre>
 
=={{header|J}}==
'''Solution''' (''explicit''):<langsyntaxhighlight lang="j"> spkln =: verb define
y spkln~ 4 u:16b2581+i.8 NB. ▁▂▃▄▅▆▇█
:
Line 792 ⟶ 1,256:
N =. # x
x {~ <. (N-1) * (y-MIN) % MAX-MIN
)</langsyntaxhighlight>
'''Solution''' (''tacit''):<langsyntaxhighlight lang="j"> spkln =: (4 u:16b2581+i.8)&$: : ([ {~ <:@#@[ <.@* ] (- % >./@[ - ]) <./@])</langsyntaxhighlight>
'''Solution''' (''look Ma, no hands!''):<langsyntaxhighlight lang="j"> spkln =: (u:9601+i.8)&$: : ([ {~ ((<.@* <:@#)~ ((- % (- >./))~ <./)))</langsyntaxhighlight>
'''Examples''':<pre> spkln 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
Line 804 ⟶ 1,268:
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">
public class Sparkline
{
Line 846 ⟶ 1,310:
}
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 855 ⟶ 1,319:
 
</pre>
 
 
=={{header|JavaScript}}==
Line 861 ⟶ 1,324:
===ES6===
 
<langsyntaxhighlight JavaScriptlang="javascript">(() => {
'use strict';
 
//const sparkLinemain ::= [Num]() -=> String{
let sparkLine = xs => {
let min = minimumBy(numericOrdering, xs),
max = maximumBy(numericOrdering, xs),
range = max - min;
 
// sparkLine :: [Num] -> String
return xs.map(x => ((x - min) * 7) / range)
const sparkLine = xs => .map({
const nhist => dataBins(n >= 0 && n < 8) ? '▁▂▃▄▅▆▇█'(xs);
return .splitunlines('')[Math.round(n)] : undefined
).joinconcat(map('');
i => '▁▂▃▄▅▆▇█' [i],
},
hist.indexes
)),
unwords(xs),
[
'Min: ' + hist.min,
'Mean: ' + hist.mean.toFixed(2),
'Median: ' + hist.median,
'Max: ' + hist.max,
].join('\t'),
''
]);
};
 
 
// maximumBy :: (a -> a -> Ordering) -> [a] -> a
maximumBy// =dataBins (f,:: xs)Int =-> [Num] ->
// xs.reduce((a {indexes:: [Int], x)min:: =>Float, max:: Float,
// arange ===:: undefinedFloat, ? xlbounds :: ([Float]}
const dataBins = intBins => xs f(x, a) => 0 ? x : a{
const
iLast = intBins - 1,
ys = sort(xs),
mn = ys[0],
mx = last(ys),
rng = mx - mn,
w = rng / intBins,
lng = xs.length,
mid = lng / 2,
lbounds = map(
i => mn + (w * i),
enumFromTo(1, iLast)
);
return {
indexes: map(
x => {
const mb = findIndex(b => b > x, lbounds);
return mb.Nothing ? (
iLast
) : mb.Just;
},
xs
),
undefinedlbounds: lbounds,
) min: mn,
median: even(lng) ? (
sum([ys[mid - 1], ys[mid]]) / 2
) : ys[Math.floor(mid)],
mean: sum(xs) / lng,
max: mx,
range: rng
};
};
 
// numbersFromString :: String -> [Float]
const numbersFromString = s =>
map(x => parseFloat(x, 10),
s.split(/[,\s]+/)
);
 
return unlines(map(
// minimumBy :: (a -> a -> Ordering) -> [a] -> a
minimumBy = compose(fsparkLine, xsnumbersFromString) =>,
xs.reduce((a, x) =>[
a'0, ===1, undefined19, ? x : (20',
'0, 999, 4000, 4999, f(x7000, a) < 0 ? x : a7999',
)'1 2 3 4 5 6 7 8 7 6 5 4 3 2 1',
undefined'1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5'
),]
));
};
 
// GENERIC FUNCTIONS ----------------------------
numericOrdering = (a, b) => a < b ? -1 : (a > b ? 1 : 0);
 
// TESTJust :: a -> Maybe a
const Just = x => ({
type: 'Maybe',
Nothing: false,
Just: x
});
 
// Nothing :: Maybe a
return ["1 2 3 4 5 6 7 8 7 6 5 4 3 2 1",
const Nothing = () => ({
"1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5",
type: 'Maybe',
"3 2 1 0 -1 -2 -3 -4 -3 -2 -1 0 1 2 3",
Nothing: true,
"-1000 100 1000 500 200 -400 -700 621 -189 3"
].map(});
s => s.split(/[,\s]+/)
.map(x => parseFloat(x, 10))
).map(sparkLine);
 
// compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
})();</lang>
const compose = (f, g) => x => f(g(x));
 
// concat :: [[a]] -> [a]
// concat :: [String] -> String
const concat = xs =>
0 < xs.length ? (() => {
const unit = 'string' !== typeof xs[0] ? (
[]
) : '';
return unit.concat.apply(unit, xs);
})() : [];
 
 
<pre>["▁▂▃▄▅▆▇█▇▆▅▄▃▂▁","▂▁▄▃▆▅█▇","█▇▆▅▄▃▂▁▂▃▄▅▆▇█","▁▅█▆▅▃▂▇▄▅"]</pre>
// enumFromTo :: (Int, Int) -> [Int]
const enumFromTo = (m, n) =>
Array.from({
length: 1 + n - m
}, (_, i) => m + i);
 
// even :: Int -> Bool
const even = n => 0 === n % 2;
 
// last :: [a] -> a
const last = xs =>
0 < xs.length ? xs.slice(-1)[0] : undefined;
 
// map :: (a -> b) -> [a] -> [b]
const map = (f, xs) =>
(Array.isArray(xs) ? (
xs
) : xs.split('')).map(f);
 
// sort :: Ord a => [a] -> [a]
const sort = xs => xs.slice()
.sort((a, b) => a < b ? -1 : (a > b ? 1 : 0));
 
 
// findIndex :: (a -> Bool) -> [a] -> Maybe Int
const findIndex = (p, xs) => {
const
i = (
'string' !== typeof xs ? (
xs
) : xs.split('')
).findIndex(p);
return -1 !== i ? (
Just(i)
) : Nothing();
};
 
// sum :: [Num] -> Num
const sum = xs => xs.reduce((a, x) => a + x, 0);
 
// unlines :: [String] -> String
const unlines = xs => xs.join('\n');
 
// unwords :: [String] -> String
const unwords = xs => xs.join(' ');
 
// MAIN ---
return main();
})();</syntaxhighlight>
{{Out}}
<pre>▁▁██
0 1 19 20
Min: 0 Mean: 10.00 Median: 10 Max: 20
 
▁▁▅▅██
0 999 4000 4999 7000 7999
Min: 0 Mean: 4166.17 Median: 4499.5 Max: 7999
 
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
Min: 1 Mean: 4.27 Median: 4 Max: 8
 
▂▁▄▃▆▅█▇
1.5 0.5 3.5 2.5 5.5 4.5 7.5 6.5
Min: 0.5 Mean: 4.00 Median: 4 Max: 7.5</pre>
 
=={{header|jq}}==
<langsyntaxhighlight lang="jq">def sparkline:
min as $min
| ( (max - $min) / 7 ) as $div
Line 923 ⟶ 1,508:
def string2array:
def tidy: select( length > 0 );
[split(" ") | .[] | split(",") | .[] | tidy | tonumber];</langsyntaxhighlight>
'''Task'''
( "1 2 3 4 5 6 7 8 7 6 5 4 3 2 1",
Line 934 ⟶ 1,519:
 
=={{header|Julia}}==
<syntaxhighlight lang="julia">function sparklineit(arr)
<lang Julia>
sparkchars = '\u2581':'\u2588'
function sparklineit(a)
dyn = length(sparkchars)
const sparkchars = '\u2581':'\u2588'
constlo, dynhi = lengthextrema(sparkcharsarr)
b = @. max(ceil(Int, dyn * (arr - lo) / (hi - lo)), 1)
(lo, hi) = extrema(a)
return join(sparkchars[b])
b = max(iceil(dyn*(a-lo)/(hi-lo)), 1)
return join(sparkchars[b], "")
end
 
v = rand(0:10, 10)
function getnumbers(s)
println("$v → ", sparklineit(v))
a = split(s, r"[,,\s]+")
v = 10rand(10)
a = try
println("$(round.(v, 2)) → ", sparklineit(v))
map(parseint, a)
catch
map(parsefloat, a)
end
end
 
test = getnumbers("1 2 3 4 5 6 7 8 7 6 5 4 3 2 1")
println(test, " => ", sparklineit(test))
 
test = getnumbers("1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5")
println(test, " => ", sparklineit(test))
</lang>
 
lines = strip.(split("""
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""", "\n"))
arrays = map(lin -> split(lin, r"\s+|\s*,\s*") .|> s -> parse(Float64, s), lines)
foreach(v -> println("$v → ", sparklineit(v)), arrays)
</syntaxhighlight>
{{out}}
<pre>[6, 3, 9, 5, 1, 10, 0, 1, 3, 6] → ▅▃█▄▁█▁▁▃▅
<pre>
[0.57, 0.14, 4.73, 6.61, 6.9, 0.8, 9.71, 7.39, 2.75, 5.7] → ▁▁▄▆▆▁█▇▃▅
[1,2,3,4,5,6,7,8,7,6,5,4,3,2,1] => ▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
[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] => ▂▁▄▃▆▅█▇
[1.5, 0.5, 3.5, 2.5, 5.5, 4.5, 7.5, 6.5] → ▂▁▄▃▆▅█▇</pre>
</pre>
 
=={{header|Kotlin}}==
{{trans|Java}}
<langsyntaxhighlight lang="scala">internal const val bars = "▁▂▃▄▅▆▇█"
internal const val n = bars.length - 1
 
fun <T: Number> Iterable<T>.toSparkline(): String {
Line 988 ⟶ 1,567:
println(s2)
println(s2.toSparkline())
}</langsyntaxhighlight>
{{Out}}
<pre>1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
Line 996 ⟶ 1,575:
 
=={{header|LiveCode}}==
<langsyntaxhighlight LiveCodelang="livecode">command sparklines listOfNums
local utfbase=0x2581
local tStats, utfp, tmin,tmax,trange
Line 1,017 ⟶ 1,596:
end repeat
put plot
end sparklines</langsyntaxhighlight>
 
Test
Line 1,027 ⟶ 1,606:
Min: 0.5 Max: 7.5 Range: 7 Mean 4 Stdev: 2.44949 Variance: 6
▂▁▄▃▆▅█▇</pre>
 
=={{header|M2000 Interpreter}}==
This statement a=cdr(a) make a new array from a excluding the first item, so can be return the empty array (,). In Row$(a) a is passing by value, but is a pointer to array, so we get a pointer to point to same array. When we do the a=cdr(a) we change pointer so variable (a) point to a new array.
 
 
The first program use auto arrays (or tuple), so we have to convert to string for output to clipboard (Print dat can be used to print the array as is to screen), and the second program get the input as string, so we have to make it an array at execution time, using then param() for inline parameters in expressions. A Random(param("1,10")) is the same as Random(1,10) (we can use only literal values in param(string_arg)). Because dat get from dat$ only the data, we can use Eval$("("+dat$+")"). Eval$() get all string as an expression for evaluation.
 
 
 
<syntaxhighlight lang="m2000 interpreter">
Module CheckIt {
Function Row$(a) {
def item$(a)=str$(car(a)#val(0),0)
rep$=item$(a)
while len(a)
rep$+=", "+item$(a)
a=cdr(a)
End While
=rep$
}
Font "Dejavu Sans Mono"
Cls
Const bar$="▁▂▃▄▅▆▇█"
Document doc$
data1=(1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1)
data2=(1.5, 0.5, 3.5, 2.5, 5.5, 4.5, 7.5, 6.5)
SparkLine(data1)
SparkLine(data2)
Clipboard doc$
Sub SparkLine(dat as array)
Local min=dat#min(), range=(dat#max()-dat#min()), range1=7/range
Local item, rep$="Input:"+Row$(dat)+{
}
item=each(dat)
While item
rep$+=Mid$(bar$,(array(item)-min)*range1+1 ,1)
End While
rep$+=" ("+str$(range,1033)+")"
doc$=rep$+{
}
Report rep$
End Sub
}
Checkit
</syntaxhighlight>
 
Function Param() get a string an put it as inline code in expressions
 
<syntaxhighlight lang="m2000 interpreter">
Module CheckIt {
Font "Dejavu Sans Mono"
Cls
Const bar$="▁▂▃▄▅▆▇█"
Document doc$
data1$="1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1"
data2$="1.5, 0.5, 3.5, 2.5, 5.5, 4.5, 7.5, 6.5"
SparkLine(data1$)
SparkLine(data2$)
Clipboard doc$
Sub SparkLine(dat$)
dat=(param(dat$))
Rem dat=eval$("("+dat$+")")
Local min=dat#min(), range=(dat#max()-dat#min()), range1=7/range
Local item, rep$="Input:"+dat$+{
}
item=each(dat)
While item
rep$+=Mid$(bar$,(array(item)-min)*range1+1 ,1)
End While
rep$+=" ("+str$(range,1033)+")"
doc$=rep$+{
}
Report rep$
End Sub
}
Checkit
</syntaxhighlight>
 
Third program use strings for stack input, which skip coma as white space. We have to pass to current stack, here calling a function (which always have a new stack for values). First we flush the stack (make it empty), then we use Stack Dat$ to parse the dat$ (also empty the string). Last we rtuern an array using array() using as argument a stack object. Read only function [] do two things replace the current stack object with an empty one, and return the old stack.
 
 
<syntaxhighlight lang="m2000 interpreter">
Module CheckIt {
Function ExtractDat(dat$) {
Flush
Stack dat$
=array([])
}
Font "Dejavu Sans Mono"
Cls
Const bar$="▁▂▃▄▅▆▇█"
Document doc$
data1$="1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1"
data2$="1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5 "
SparkLine(data1$)
SparkLine(data2$)
Clipboard doc$
Sub SparkLine(dat$)
dat=ExtractDat(dat$)
Rem dat=eval$("("+dat$+")")
Local min=dat#min(), range=(dat#max()-dat#min()), range1=7/range
Local item, rep$="Input:"+dat$+{
}
item=each(dat)
While item
rep$+=Mid$(bar$,(array(item)-min)*range1+1 ,1)
End While
rep$+=" ("+str$(range,1033)+")"
doc$=rep$+{
}
Report rep$
End Sub
}
Checkit
</syntaxhighlight>
{{out}}
<pre>
Input:1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁ (7)
Input:1.5, 0.5, 3.5, 2.5, 5.5, 4.5, 7.5, 6.5
▂▁▄▃▆▅█▇ (7)
</pre >
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">toSparkline[data_String] := FromCharacterCode[Round[7 Rescale@Flatten@ImportString[data, "Table", "FieldSeparators" -> {" ", ","}]] + 16^^2581];</syntaxhighlight>
<pre>
toSparkline["1 2 3 4 5 6 7 8 7 6 5,4 3 2 1 "]
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
 
toSparkline[" 1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5 "]
▂▁▄▃▆▅█▇
</pre>
 
=={{header|NetRexx}}==
<langsyntaxhighlight NetRexxlang="netrexx">/* NetRexx */
options replace format comments java crossref symbols nobinary
 
Line 1,083 ⟶ 1,794:
return
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,091 ⟶ 1,802:
Input: 1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5
Sparkline: ▂▁▄▃▆▅█▇
</pre>
 
=={{header|Mathematica}}==
<lang Mathematica>toSparkline[data_String] := FromCharacterCode[Round[7 Rescale@Flatten@ImportString[data, "Table", "FieldSeparators" -> {" ", ","}]] + 16^^2581];</lang>
<pre>
toSparkline["1 2 3 4 5 6 7 8 7 6 5,4 3 2 1 "]
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
 
toSparkline[" 1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5 "]
▂▁▄▃▆▅█▇
</pre>
 
=={{header|Nim}}==
{{trans|Python}}
<langsyntaxhighlight lang="nim">import rdstdin, strutilssequtils, unicodestrutils
 
const bar = [9601"\u2581", 9602"\u2582", 9603"\u2583", 9604"\u2584", 9605"\u2585", 9606"\u2586", 9607"\u2587", 9608"\u2588"]
const barcount = float(bar.high)
 
while Truetrue:
let
line = readLineFromStdin "Numbers please separated by space/commas: "
numbers = line.split({' ', ','}).filterIt(it.len != 0).map(parseFloat)
mn = min(numbers)
mx = max(numbers)
Line 1,119 ⟶ 1,820:
var sparkline = ""
for n in numbers:
let i = int((n - mn) / extent * barcount)
sparkline.add($TRune( bar[i]))
echo "min: ", mn.formatFloat(precision = 0), "; max: ", mx.formatFloat(precision = 0-1)
echo sparkline</langsyntaxhighlight>
{{out}}
<pre>Numbers please separated by space/commas: 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
Line 1,131 ⟶ 1,832:
▂▁▄▃▆▅█▇</pre>
 
=={{header|PerlOCaml}}==
<syntaxhighlight lang="ocaml">let before_first_bar = 0x2580
<lang perl>binmode(STDOUT, ":utf8");
let num_bars = 8
 
sublet sparkline {numbers =
let max_num = List.fold_left max 0. numbers in
my $s = shift;
let scale = float_of_int num_bars /. max_num in
my @n = split(/[\s,]+/,$s);
let bars = Buffer.create num_bars in
return unless @n;
let add_bar number =
my($min,$max) = ($n[0],$n[0]);
let scaled = scale *. number |> Float.round |> int_of_float in
for my $v (@n) { $min = $v if $v < $min; $max = $v if $v > $max; }
if scaled <= 0 then
printf "min: %5f; max %5f\n", $min, $max;
(* Using underscore character to differentiate between zero and one *)
my @bars = map { chr($_) } 0x2581 .. 0x2588;
Buffer.add_char bars '_'
my $div = ($max - $min) / $#bars;
else
print join("", map { $bars[$div ? ($_-$min) / $div : @bars/2] } @n), "\n";
scaled + before_first_bar |> Uchar.of_int |> Buffer.add_utf_8_uchar bars
1;
in
}
List.iter add_bar numbers;
Buffer.contents bars
 
let print_sparkline line =
while (1) {
printPrintf.printf "Numbers separated by spaces/commas: %s\n" line;
line
exit unless sparkline(scalar(<>));
|> String.trim
}</lang>
|> String.split_on_char ' '
|> List.map (String.split_on_char ',')
|> List.flatten
|> List.filter_map (function
| "" -> None
| number -> Some (float_of_string number))
|> sparkline
|> print_endline
 
let () =
"0 0 1 1; 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 "
|> String.trim
|> String.split_on_char ';'
|> List.iter print_sparkline
</syntaxhighlight>
{{out}}
<pre>
Numbers: 0 0 1 1
Numbers separated by spaces/commas: 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
__██
min: 1.000000; max 8.000000
Numbers: 0 1 19 20
__██
Numbers: 0 999 4000 4999 7000 7999
_▁▄▅▇█
Numbers:
1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
Numbers:
Numbers separated by spaces/commas: 1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5"
1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5
min: 0.500000; max 7.500000
▂▁▄▃▆▅█▇
</pre>
Numbers separated by spaces/commas: 9 18 27 36 45 54 63 72 63 54 45 36 27 18 9
 
min: 9.000000; max 72.000000
=={{header|Perl}}==
<syntaxhighlight lang="perl">binmode(STDOUT, ":utf8");
our @sparks=map {chr} 0x2581 .. 0x2588;
sub sparkline :prototype(@) {
my @n=map {0+$_} grep {length} @_ or return "";
my($min,$max)=($n[0])x2;
if (@n>1) {
for (@n[1..$#n]) {
if ($_<$min) { $min=$_ }
elsif ($_>$max) { $max=$_ }
}
}
my $sparkline="";
for(@n) {
my $height=int( $max==$min ? @sparks/2 : ($_-$min)/($max-$min)*@sparks );
$height=$#sparks if $height>$#sparks;
$sparkline.=$sparks[$height];
}
my $summary=sprintf "%d values; range %s..%s", scalar(@n), $min, $max;
return wantarray ? ($summary, "\n", $sparkline, "\n") : $sparkline;
}
 
# one number per line
# print sparkline( <> );
 
# in scalar context, get just the sparkline without summary or trailing newline
# my $sl=sparkline( <> ); print $sl;
 
# one sparkline per line
print sparkline( split /[\s,]+/ ) while <>;
</syntaxhighlight>
{{out}}
<pre>
$ echo 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1 | perl -Mstrict -w spark.pl # strict and warn not needed but it passes both
15 values; range 1..8
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
 
Numbers separated by spaces/commas: 3 2 1 0 -1 -2 -3 -4 -3 -2 -1 0 1 2 3
$ echo 0 1 19 20 | perl spark.pl
min: -4.000000; max 3.000000
4 values; range 0..20
█▇▆▅▄▃▂▁▂▃▄▅▆▇█
▁▁██
Numbers separated by spaces/commas: 12 12 12 12
 
min: 12.000000; max 12.000000
$ echo 0 999 4000 4999 7000 7999 | perl spark.pl
▁▁▁▁
6 values; range 0..7999
Numbers separated by spaces/commas:
▁▁▅▅██
 
$ echo 1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5 | perl spark.pl
8 values; range 0.5..7.5
▂▁▄▃▆▅█▇
 
$ echo -9e9 1.2345 6e5 | perl spark.pl
3 values; range -9000000000..600000
▁██
 
$ echo 12 12 12 12 | perl spark.pl
4 values; range 12..12
▅▅▅▅
</pre>
Most Perl builds have [https://en.wikipedia.org/wiki/IEEE_754-2008_revision IEEE-754 floats]:
<pre>
$ echo {1..8}e307 | perl spark.pl
8 values; range 1e+307..8e+307
▁▂▃▄▅▆▇█
 
$ echo {1..8}e308 | perl spark.pl
=={{header|Perl 6}}==
8 values; range 1e+308..Inf
<lang perl6>constant @bars = '▁' ... '█';
▁▁▁▁▁▁▁▁
while prompt 'Numbers separated by anything: ' -> $_ {
 
my @numbers = map +*, .comb(/ '-'? \d+ ['.' \d+]? /);
$ echo -{1..8}e307 | perl spark.pl
my ($mn,$mx) = @numbers.minmax.bounds;
8 values; range -8e+307..-1e+307
say "min: $mn.fmt('%5f'); max: $mx.fmt('%5f')";
█▇▆▅▄▃▂▁</pre>
my $div = ($mx - $mn) / (@bars - 1);
 
say @bars[ (@numbers X- $mn) X/ $div ].join;
=={{header|Phix}}==
}</lang>
Works fine on Linux, with or without unicode_console.e as that does little apart from check environment settings for clues, but on my Windows box, on which it invokes kernel32/SetConsoleOutputCP(CP_UTF8), unicode_console.e improves it only slightly, getting just two of the eight characters right. Changing the font on the windows(10) console to "NSimSum" or "SimSun-ExtB" (manually, by right clicking on the title bar and selecting properties/fonts) improves things considerably - suggestions welcome.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #7060A8;">requires</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"1.0.2"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (a fix for JS)</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">unicode_console</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"0 1 19 20"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"0 0 1 1"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"0 999 4000 4999 7000 7999"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"1 1 2 2 3 3"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"1 2 3 4 5 6 7 8 7 6 5 4 3 2 1"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5"</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">ti</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split_any</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #008000;">" ,"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]}}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">scanf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"%f"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">mn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">mx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">range</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">mn</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Min :%g, Max :%g, Range :%g\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">mn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">mx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">range</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">unicode_console</span><span style="color: #0000FF;">()</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">ti</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">#2581</span> <span style="color: #0000FF;">+</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">((</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]-</span><span style="color: #000000;">mn</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">range</span><span style="color: #0000FF;">*</span><span style="color: #000000;">8</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">utf32_to_utf8</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">else</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"unicode is not supported\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
<pre>Numbers separated by anything: 9 18 27 36 45 54 63 72 63 54 45 36 27 18 9
Min :0, Max :20, Range :20
9 18 27 36 45 54 63 72 63 54 45 36 27 18 9
▁▁██
min: 9.000000; max: 72.000000
Min :0, Max :1, Range :1
▁▁██
Min :0, Max :7999, Range :7999
▁▁▅▅██
Min :1, Max :3, Range :2
▁▁▅▅██
Min :1, Max :8, Range :7
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
Min :0.5, Max :7.5, Range :7
Numbers separated by anything: 1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5
1.5 0.5 3.5 2.5 5.5 4.5 7.5 6.5
min: 0.500000; max: 7.500000
▂▁▄▃▆▅█▇
</pre>
Numbers separated by anything: 3 2 1 0 -1 -2 -3 -4 -3 -2 -1 0 1 2 3
min: -4.000000; max: 3.000000
█▇▆▅▄▃▂▁▂▃▄▅▆▇█
Numbers separated by anything: ^D</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(de sparkLine (Lst)
(let (Min (apply min Lst) Max (apply max Lst) Rng (- Max Min))
(for N Lst
(prin
(char (+ 9601 (*/ (- N Min) 7 Rng)) ) ) )
(prinl) ) )</langsyntaxhighlight>
Test:
<langsyntaxhighlight PicoLisplang="picolisp">(sparkLine (str "1 2 3 4 5 6 7 8 7 6 5 4 3 2 1"))
(sparkLine (scl 1 (str "1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5")))</langsyntaxhighlight>
Output:
<pre>▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
Line 1,209 ⟶ 2,022:
 
=={{header|Python}}==
<syntaxhighlight lang="python"># -*- coding: utf-8 -*-
<lang python>import re
try: raw_input
except: raw_input = input
 
# Unicode: 9601, 9602, 9603, 9604, 9605, 9606, 9607, 9608
try: bar = u'▁▂▃▄▅▆▇█'
barcount = len(bar)
except: bar = '▁▂▃▄▅▆▇█'
 
barcount = len(bar) - 1
def sparkline(numbers):
while True:
line = raw_input('Numbers please separated by space/commas: ')
numbers = [float(n) for n in re.split(r'[\s,]+', line.strip())]
mn, mx = min(numbers), max(numbers)
extent = mx - mn
sparkline = ''.join(bar[intmin( (n[barcount - mn) / extent * barcount)]1,
int((n - mn) / extent * barcount)])]
for n in numbers)
print('min:return %5f; max: %5f' % (mn, mx)), sparkline
 
print(sparkline)</lang>
if __name__ == '__main__':
import re
for line in ("0 0 1 1; 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 ").split(';'):
print("\nNumbers:", line)
numbers = [float(n) for n in re.split(r'[\s,]+', line.strip())]
mn, mx, sp = sparkline(numbers)
print(' min: %5f; max: %5f' % (mn, mx))
print(" " + sp)</syntaxhighlight>
 
{{out}}
<pre>
<pre>Numbers separated by space/commas: 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
Numbers: 0 0 1 1
min: 1.000000; max: 7.000000
min: 0.000000; max: 1.000000
▁▁██
 
Numbers: 0 1 19 20
min: 0.000000; max: 20.000000
▁▁██
 
Numbers: 0 999 4000 4999 7000 7999
min: 0.000000; max: 7999.000000
▁▁▅▅██
 
Numbers: 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
min: 1.000000; max: 8.000000
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
 
Numbers: 1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5
min: 0.500000; max: 7.500000
▂▁▄▃▆▅█▇</pre>
 
 
 
Or, by composition of pure functions, with type comments for the reader, rather than the compiler.
 
To vary the approach, the block used is derived from the option type (<code>Just x | Nothing</code>) result of a search over 7 zero-indexed lower bounds [0..6].
 
If a lower bound whose value exceeds that of the given data point can be found, we just use the index of that bound.
 
If the search result is 'not found' (Nothing), then we use the highest (nominally 8th, or index 7) block.
 
<syntaxhighlight lang="python">'''Sparkline in Unicode'''
 
from functools import reduce
import operator
import re
 
 
# ------------------- LABELLED SPARKLINE -------------------
 
# sparkLine :: [Float] -> [String]
def sparkLine(xs):
'''Unicode sparkline summary of a
list of floating point numbers.
'''
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)))
le = curry(operator.le)
# spark :: Float -> Char
def spark(x):
def go(i):
return '▁▂▃▄▅▆▇'[i]
return maybe('█')(go)(
findIndex(le(x))(lbounds)
)
return [
''.join(map(spark, 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 []
 
 
# -------------------------- TEST --------------------------
# main :: IO ()
def main():
'''Tested on some sample lists.
'''
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):
'''Constructor for an inhabited Maybe (option type) value.
Wrapper containing the result of a computation.
'''
return {'type': 'Maybe', 'Nothing': False, 'Just': x}
 
 
# Nothing :: Maybe a
def Nothing():
'''Constructor for an empty Maybe (option type) value.
Empty wrapper returned where a computation is not possible.
'''
return {'type': 'Maybe', 'Nothing': True}
 
 
# compose :: ((a -> a), ...) -> (a -> a)
def compose(*fs):
'''Composition, from right to left,
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)
 
 
# curry :: ((a, b) -> c) -> a -> b -> c
def curry(f):
'''A curried function derived
from an uncurried function.
'''
return lambda x: lambda y: f(x, y)
 
 
# even :: Int -> Bool
def even(x):
'''True if x is an integer
multiple of two.
'''
return 0 == x % 2
 
 
# findIndex :: (a -> Bool) -> [a] -> Maybe Int
def findIndex(p):
'''Just the first index at which an
element in xs matches p,
or Nothing if no elements match.
'''
def go(xs):
try:
return Just(next(
i for i, v in enumerate(xs) if p(v)
))
except StopIteration:
return Nothing()
return go
 
 
# maybe :: b -> (a -> b) -> Maybe a -> b
def maybe(v):
'''Either the default value v, if m is Nothing,
or the application of f to x,
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
def mean(xs):
'''The arithmetic mean of the numeric
values in xs.
'''
return sum(xs) / float(len(xs))
 
 
# readFloats :: String -> [Float]
def readFloats(s):
'''A list of floats parsed from
a numeric string delimited by
commas and/or white space.
'''
return list(map(
float,
re.split(r'[\s,]+', s)
))
 
 
# unlines :: [String] -> String
def unlines(xs):
'''A single string formed by the intercalation
of a list of strings with the newline character.
'''
return '\n'.join(xs)
 
 
# MAIN ---
if __name__ == '__main__':
main()</syntaxhighlight>
{{Out}}
<pre>▁▁██
0.0 1.0 19.0 20.0
Min 0.0 Mean 10.0 Median 10.0 Max 20.0
 
▁▁▅▅██
0.0 999.0 4000.0 4999.0 7000.0 7999.0
Min 0.0 Mean 4166.17 Median 4499.5 Max 7999.0
 
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
Numbers1.0 separated2.0 by3.0 space/commas: 14.0 5,.0 6.0 7.50 38.5,0 27.50 56.0 5,.0 4.50 73.5,0 62.50 1.0
Min 1.0 Mean 4.27 Median 4.0 Max 8.0
 
▂▁▄▃▆▅█▇
1.5 0.5 3.5 2.5 5.5 4.5 7.5 6.5
Min 0.5 Mean 4.0 Median 4.0 Max 7.5</pre>
 
=={{header|R}}==
<syntaxhighlight lang="rsplus">
bars <- intToUtf8(seq(0x2581, 0x2588), multiple = T) # ▁ ▂ ▃ ▄ ▅ ▆ ▇ █
n_chars <- length(bars)
 
sparkline <- function(numbers) {
mn <- min(numbers)
mx <- max(numbers)
interval <- mx - mn
 
bins <- sapply(
numbers,
function(i)
bars[[1 + min(n_chars - 1, floor((i - mn) / interval * n_chars))]]
)
sparkline <- paste0(bins, collapse = "")
 
return(sparkline)
}
 
sparkline(c(1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1))
sparkline(c(1.5, 0.5, 3.5, 2.5, 5.5, 4.5, 7.5, 6.5))
sparkline(c(0, 999, 4000, 4999, 7000, 7999))
sparkline(c(0, 0, 1, 1))
sparkline(c(0, 1, 19, 20))
</syntaxhighlight>
{{out}}
<syntaxhighlight lang="r">
[1] "▂▁▄▃▆▅█▇"
[1] "▁▂▃▄▅▆▇█▇▆▅▄▃▂▁"
[1] "▂▁▄▃▆▅█▇"
[1] "▁▁▅▅██"
[1] "▁▁██"
[1] "▁▁██"
</syntaxhighlight>
 
=={{header|Racket}}==
<syntaxhighlight lang="racket">
#lang racket (require syntax/parse)
 
(define bars "▁▂▃▄▅▆▇█")
(define bar-count (string-length bars))
 
(define (sparks str)
(define ns (map string->number (string-split str #rx"[ ,]" #:repeat? #t)))
(define mn (apply min ns))
(define bar-width (/ (- (apply max ns) mn) (- bar-count 1)))
(apply string (for/list ([n ns]) (string-ref bars (exact-floor (/ (- n mn) bar-width))))))
 
(sparks "1 2 3 4 5 6 7 8 7 6 5 4 3 2 1")
(sparks "1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5")
</syntaxhighlight>
{{out}}
<syntaxhighlight lang="racket">
"▁▂▃▄▅▆▇█▇▆▅▄▃▂▁"
"▂▁▄▃▆▅█▇"
</syntaxhighlight>
 
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" line>constant @bars = '▁' ... '█';
while prompt 'Numbers separated by anything: ' -> $_ {
my @numbers = map +*, .comb(/ '-'? [[\d+ ['.' \d*]?] | ['.' \d+]] /);
my ($mn,$mx) = @numbers.minmax.bounds;
say "min: $mn.fmt('%5f'); max: $mx.fmt('%5f')";
say @bars[ @numbers.map: { @bars * ($_ - $mn) / ($mx - $mn) min @bars - 1 } ].join;
}</syntaxhighlight>
{{out}}
<pre>Numbers separated by anything: 9 18 27 36 45 54 63 72 63 54 45 36 27 18 9
9 18 27 36 45 54 63 72 63 54 45 36 27 18 9
min: 9.000000; max: 72.000000
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
Numbers separated by anything: 1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5
1.5 0.5 3.5 2.5 5.5 4.5 7.5 6.5
min: 0.500000; max: 7.500000
▂▁▄▃▆▅█▇</pre>
Numbers separated by anything: 3 2 1 0 -1 -2 -3 -4 -3 -2 -1 0 1 2 3
min: -4.000000; max: 3.000000
█▇▆▅▄▃▂▁▂▃▄▅▆▇█
Numbers separated by anything: ^D</pre>
 
=={{header|REXX}}==
Line 1,240 ⟶ 2,353:
{{Works with|ooRexx}}
{{Works with|Regina|3.4}}
<langsyntaxhighlight REXXlang="rexx">/* Rexx */
 
parse arg aaa
Line 1,307 ⟶ 2,420:
return
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,318 ⟶ 2,431:
 
===version 2===
(A re-work of REXX version 1)<br>
 
This version works on:
::* all versions of Regina (which may or may not support ''single line comments'')
::* R4 and ROO (which don't support ''single line comments'')
::* older versions of REXX such as PC/REXX and Personal REXX which don't support the '''changestr''' BIF
 
This version also removed some dead code, simplified the program structure and subroutines, added comments.
 
<br>''Single line comments'' were introduced in Regina 3.4.
Single line comments'' were introduced in Regina 3.4.
<br>Regina 3.6 introducted the options: &nbsp; ''single_line_comments'' and ''noSingle_line_comments''.
 
<br>It should also be noted that the CMS and TSO versions of REXX (and others) don't support ''single line comments''.
Regina 3.6 introduced the options: &nbsp; ''single_line_comments'' and ''noSingle_line_comments''.
<lang rexx>/*REXX program displays a sparkline (spark graph) for a group of values.*/
 
if arg()==0 then do /*No arguments? Use defaults.*/
It should also be noted that the CMS and TSO versions of REXX (and practically all others) don't support ''single line comments''.
call sparkGraph 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
<syntaxhighlight lang="rexx">/*REXX program displays a sparkline (spark graph) for a group of values. */
call sparkGraph '1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5'
if arg()==0 then do /*Optional arguments? Then use defaults*/
call sparkGraph 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
call sparkGraph '1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5'
end
else call sparkGraph arg(1)
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────CEIL subroutine─────────────────────*/
ceil: procedure; parse arg ?; _=trunc(?); return _+(?>0)*(?\=_)
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────SPARKGRAPH subroutine───────────────*/
sparkGraph: procedure; parse arg x; say ' input: ' x /*echo the values.*/
x= translate(x, ' ', ",") /*remove any superfluous commas. */
$='▁▂▃▄▅▆▇█' $= '▁▂▃▄▅▆▇█'; L= length($) /*chars to be used for the graph.*/
xmin= word(x, 1); xmax=xmin xmax= xmin /*assume a minimum and a maximum.*/
 
do n=2 to words(x); _= word(x, n) /*examine successive words in X.*/
xmin= min(_, xmin) /*find the minimum value in X. */
xmax= max(_, xmax) /* " " maximum " " " */
end /*n*/
z=
do j=1 for words(x) /*build the output spark graph. */
z= z || substr($, ceil( ( word(x, j) -xmin+1) / (xmax -xmin+1) * L), 1)
end /*j*/
 
z=; do j=1 for words(x) say 'output: ' z; say; return /*buildshow the output, spark+ graph.a blank line*/</syntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
z=z||substr($,ceil((word(x,j)-xmin+1)/(xmax-xmin+1)*length($)),1)
end /*j*/
 
say 'output: ' z; say /*show the output, + a blank line*/
return</lang>
{{out}} using the default input(s):
<pre>
input: 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
Line 1,361 ⟶ 2,478:
output: ▂▁▄▃▆▅█▇
</pre>
 
=={{header|Racket}}==
<lang racket>
#lang racket (require syntax/parse)
 
(define bars "▁▂▃▄▅▆▇█")
(define bar-count (string-length bars))
 
(define (sparks str)
(define ns (map string->number (string-split str #rx"[ ,]" #:repeat? #t)))
(define mn (apply min ns))
(define bar-width (/ (- (apply max ns) mn) (- bar-count 1)))
(apply string (for/list ([n ns]) (string-ref bars (exact-floor (/ (- n mn) bar-width))))))
 
(sparks "1 2 3 4 5 6 7 8 7 6 5 4 3 2 1")
(sparks "1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5")
</lang>
{{out}}
<lang racket>
"▁▂▃▄▅▆▇█▇▆▅▄▃▂▁"
"▂▁▄▃▆▅█▇"
</lang>
 
=={{header|Ruby}}==
{{trans|Perl 6Raku}} with added protection for input like "0 0 0 0".
<langsyntaxhighlight lang="ruby">bar = ('▁'..'█').to_a
loop {print 'Numbers please separated by space/commas: '
numbers = gets.split(/[\s,]+/).map(&:to_f)
Line 1,393 ⟶ 2,488:
div = (max - min) / (bar.size - 1)
puts min == max ? bar.last*numbers.size : numbers.map{|num| bar[((num - min) / div).to_i]}.join
}</langsyntaxhighlight>
 
{{out}} Used Go testcases
Line 1,420 ⟶ 2,515:
 
=={{header|Rust}}==
<langsyntaxhighlight lang="rust">
const BARS: &'static str = "▁▂▃▄▅▆▇█";
 
Line 1,438 ⟶ 2,533:
print_sparkline(s2);
}
</syntaxhighlight>
</lang>
{{out}}
"▁▂▃▄▅▆▇█▇▆▅▄▃▂▁"
Line 1,445 ⟶ 2,540:
 
=={{header|S-lang}}==
<langsyntaxhighlight Slang="s-lang">
% Just to demonstrate alternate ways of defining unicode:
private variable spchrs = "\u{2581}\u{2582}\u{2583}\u{2584}\u{2585}\u{2586}\u{2587}\u{2588}";
Line 1,471 ⟶ 2,566:
sparkline("1 2 3 4 5 6 7 8 7 6 5 4 3 2 1");
sparkline("1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5 ");
</syntaxhighlight>
</lang>
{{out}}
"▁▂▃▄▅▆▇█▇▆▅▄▃▂▁"
Line 1,478 ⟶ 2,573:
 
=={{header|Scala}}==
<langsyntaxhighlight lang="scala">def mkSparks( numStr:String ) : String =
numStr.split( "[\\s,]+" ).map(_.toFloat) match {
case v if v.isEmpty => ""
Line 1,493 ⟶ 2,588:
 
// A random test...
println( mkSparks( Stream.continually( math.abs(util.Random.nextInt % 8)).take(64).mkString(" ") ))</langsyntaxhighlight>
{{out}}
<pre> ▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
Line 1,500 ⟶ 2,595:
 
=={{header|Seed7}}==
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "scanfile.s7i";
include "float.s7i";
Line 1,552 ⟶ 2,647:
data := readDataLine;
end while;
end func;</langsyntaxhighlight>
 
{{out}}
Line 1,561 ⟶ 2,656:
▂▁▄▃▆▅█▇
Numbers separated by anything:
</pre>
 
=={{header|SenseTalk}}==
This solution makes use of SenseTalk's "word" chunks, in this case delimited by any number of spaces and/or commas, to simplify parsing the input string. Also note the use of the <code>but no more than</code> operator to handle the edge case where a number equal to the top value would otherwise refer to the 9th symbol, which doesn't exist.
<syntaxhighlight lang="sensetalk">put sparklineGraph of "1 2 3 4 5 6 7 8 7 6 5 4 3 2 1"
put sparklineGraph of "1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5"
put sparklineGraph of "0, 1, 19, 20"
put sparklineGraph of "0, 999, 4000, 4999, 7000, 7999"
 
to handle sparklineGraph of input
put each word delimited by " ," of input into numbers
put the lowestValue of numbers into bottom
put the highestValue of numbers into top
put top - bottom into range -- total range of values
put range/8 into step -- the size of each incremental step in the graph
repeat with each number in numbers
put (trunc((number - bottom) / step) + 1) but no more than 8 into symbolNum
put character symbolNum of "▁▂▃▄▅▆▇█" after graph
end repeat
put !" (range: [[bottom]] to [[top]])" after graph
return graph
end sparklineGraph
</syntaxhighlight>
{{out}}
<pre>
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁ (range: 1 to 8)
▂▁▄▃▆▅█▇ (range: 0.5 to 7.5)
▁▁██ (range: 0 to 20)
▁▁▅▅██ (range: 0 to 7999)
</pre>
 
=={{header|Sidef}}==
{{trans|Ruby}}
<langsyntaxhighlight lang="ruby">var bar = @('▁'..'█');
loop {
print 'Numbers, please, separated by space/commas: ';
Line 1,573 ⟶ 2,698:
var div = ((max - min) / bar.end);
say (min == max ? bar.last*numbers.len : numbers.map{|num| bar[(num - min) / div]}.join);
}</langsyntaxhighlight>
{{out}}
<pre>Numbers, please, separated by space/commas: 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
Line 1,584 ⟶ 2,709:
=={{header|Tcl}}==
{{works with|Tcl|8.6}}
<langsyntaxhighlight lang="tcl">package require Tcl 8.6
 
proc extractValues {series} {
Line 1,598 ⟶ 2,723:
set max [tcl::mathfunc::max {*}$values]
return [join [lmap v $values {renderValue $min $max $v}] ""]
}</langsyntaxhighlight>
Demonstrating:
<langsyntaxhighlight lang="tcl">set data {
"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"
Line 1,607 ⟶ 2,732:
puts "Series: $series"
puts "Sparkline: [sparkline $series]"
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,614 ⟶ 2,739:
Series: 1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5
Sparkline: ▂▁▄▃▆▅█▇
</pre>
 
=={{header|Wren}}==
{{trans|Go}}
{{libheader|Wren-pattern}}
<syntaxhighlight lang="wren">import "io" for Stdin, Stdout
import "./pattern" for Pattern
 
var p = Pattern.new("[,+1/s|+1/s,|+1/s|,]")
 
var spark = Fn.new { |s0|
var ss = p.splitAll(s0)
var n = ss.count
var vs = List.filled(n, 0)
var min = 1/0
var max = -min
var i = 0
for (s in ss) {
var v = Num.fromString(s)
if (v.isNan || v.isInfinity) Fiber.abort("Infinities and NaN not supported.")
if (v < min) min = v
if (v > max) max = v
vs[i] = v
i = i + 1
}
var sp
if (min == max) {
sp = "▄" * n
} else {
var rs = List.filled(n, null)
var f = 8 / (max - min)
var j = 0
for (v in vs) {
var i = (f * (v - min)).floor
if (i > 7) i = 7
rs[j] = String.fromCodePoint(0x2581 + i)
j = j + 1
}
sp = rs.join()
}
return [sp, n, min, max]
}
 
while (true) {
System.print("Numbers please separated by spaces/commas or just press return to quit:")
Stdout.flush()
var numbers = Stdin.readLine().trim()
if (numbers == "") break
var res = spark.call(numbers)
var s = res[0]
var n = res[1]
var min = res[2]
var max = res[3]
if (n == 1) {
System.print("1 value = %(min)")
} else {
System.print("%(n) values. Min: %(min) Max: %(max)")
}
System.print(s)
System.print()
}</syntaxhighlight>
 
{{out}}
<pre>
Numbers please separated by spaces/commas or just press return to quit:
1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
15 values. Min: 1 Max: 8
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
 
Numbers please separated by spaces/commas or just press return to quit:
1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5
8 values. Min: 0.5 Max: 7.5
▂▁▄▃▆▅█▇
 
Numbers please separated by spaces/commas or just press return to quit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
24 values. Min: 1 Max: 24
▁▁▁▂▂▂▃▃▃▄▄▄▅▅▅▆▆▆▇▇▇███
 
Numbers please separated by spaces/commas or just press return to quit:
0 -.09 -.11 -.69 -.71 -.8
6 values. Min: -0.8 Max: 0
██▇▂▁▁
 
Numbers please separated by spaces/commas or just press return to quit:
3 3 3
3 values. Min: 3 Max: 3
▄▄▄
 
Numbers please separated by spaces/commas or just press return to quit:
1e99
1 value = 1e+99
 
Numbers please separated by spaces/commas or just press return to quit:
</pre>
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">var sparks=[0x2581..0x2588].apply("toString",-8); // int.toString(-8)-->UTF-8
var sl=(sparks.len()-1);
Line 1,625 ⟶ 2,845:
println("Range [",min,"-",max,"]", xs);
xs.pump(String,'wrap(x){ sparks[(x - min)*sl/range] }).println();
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">one:="1 2 3 4 5 6 7 8 7 6 5 4 3 2 1".split(" ").apply("toInt");
two:=("1.5, 0.5 3.5, 2.5 5.5 4.5 7.5, 6.5" - ",").split(" ").apply("toFloat");
sparkLine(one); sparkLine(two);</langsyntaxhighlight>
{{out}}
<pre>
Line 1,636 ⟶ 2,856:
▂▁▄▃▆▅█▇
</pre>
 
=={{header|Zoea}}==
<syntaxhighlight lang="zoea">
program: sparkline
input: '1 2, 3 4.5 5 6,7 8'
derive: [1,2,3,4.5,5,6,7,8]
derive: [1,2,3,4,5,6,7,8]
output: '▁▂▃▄▅▆▇█'
</syntaxhighlight>
 
=={{header|Zoea Visual}}==
[http://zoea.co.uk/examples/zv-rc/Sparkline.png Sparkline]
9,482

edits