Sparkline in unicode: Difference between revisions

m
m ((Indented edge-case tests suggested in Discussion page))
m (→‎{{header|Wren}}: Minor tidy)
 
(33 intermediate revisions by 17 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 lowerthe bounds forbetween each binbins should ideally be set to yield the following results for two particular edge cases:
 
:: <code>"0, 1, 19, 20" -> ▁▁██</code>
Line 31:
 
:: 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}}==
<langsyntaxhighlight AppleScriptlang="applescript">use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
 
on run
unlines(map(unlines, ¬
mapcompose(compose(unlines, sparkLine), readFloats), ¬
{"0, 1, 19, 20", "0, 999, 4000, 4999, 7000, 7999", ¬
"1 2 3 4 5 6 7 8 7 60, 51000, 44000, 35000, 27000, 18000", ¬
"1.5, 0.52 3.5, 2.54 5.5, 4.56 7 8 7.5, 6. 5 4 3 2 1"}))), ¬
"1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5"}))
end run
 
Line 359 ⟶ 360:
set my text item delimiters to dlm
return s
end unwords</langsyntaxhighlight>
{{Out}}
<pre>▁▁██
Line 388 ⟶ 389:
Median 4.0
Max 7.5</pre>
 
=={{header|Arturo}}==
 
<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 413 ⟶ 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 420 ⟶ 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}}==
Line 425 ⟶ 559:
===Linux version===
Accepts data via command line, prints out usage on incorrect invocation.
<syntaxhighlight lang="c">
<lang C>
#include<string.h>
#include<stdlib.h>
Line 473 ⟶ 607:
return 0;
}
</syntaxhighlight>
</lang>
Invocation and output :
<pre>
Line 486 ⟶ 620:
=={{header|C++}}==
 
<langsyntaxhighlight lang="cpp">
#include <iostream>
#include <sstream>
Line 554 ⟶ 688:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>Min: 1; Max: 8; Range: 7
Line 562 ⟶ 696:
 
=={{header|Clojure}}==
<langsyntaxhighlight Clojurelang="clojure">(defn sparkline [nums]
(let [sparks "▁▂▃▄▅▆▇█"
high (apply max nums)
Line 576 ⟶ 710:
(recur (read-line)))))
 
(spark (read-line))</langsyntaxhighlight>
 
{{Out}}
Line 585 ⟶ 719:
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">(defun buckets (numbers)
(loop with min = (apply #'min numbers)
with max = (apply #'max numbers)
Line 627 ⟶ 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 636 ⟶ 770:
=={{header|D}}==
{{trans|Python}}
<langsyntaxhighlight lang="d">void main() {
import std.stdio, std.range, std.algorithm, std.conv,
std.string, std.regex;
Line 651 ⟶ 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 663 ⟶ 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 679 ⟶ 865:
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">open System
open System.Globalization
open System.Text.RegularExpressions
Line 700 ⟶ 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 709 ⟶ 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 779 ⟶ 992:
q;1-q: {move pointer}
]#
]?</langsyntaxhighlight>
This implementation can only accept one series of numbers at a time.
{{out}}
Line 788 ⟶ 1,001:
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 861 ⟶ 1,074:
}
return
}</langsyntaxhighlight>
{{out}}
<pre>
Line 899 ⟶ 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 919 ⟶ 1,132:
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">import Data.CharList.Split (chrsplitOneOf)
import Data.List.SplitChar (splitOneOfchr)
 
 
toSparkLine :: [Double] -> [Char]String
toSparkLine xs = map cl xs
where
Line 928 ⟶ 1,142:
bot = minimum xs
range = top - bot
cl x = chr $ 0x2581 + floor (min 7 ((x - bot) / range * 8))
 
makeSparkLine :: String -> (String, Stats)
Line 974 ⟶ 1,188:
, "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"
]</langsyntaxhighlight>
{{Out}}
<pre>▁▁██
Line 992 ⟶ 1,206:
Or, stripping back a little:
{{Trans|Python}}
<syntaxhighlight lang ="haskell">import Data.List.SplitBifunctor (splitOneOfbimap)
import Data.List (findIndex)
import Data.List.Split (splitOneOf)
import Data.Maybe (maybe)
 
import Control.Arrow ((&&&))
------------------------ SPARK LINE ----------------------
 
sparkLine :: [Float] -> String
sparkLine xs[] = ""
sparkLine xxs@(x : xs) =
let (mn, mx) = (minimum &&& maximum) xs
fmap
w = (mx - mn) / 8
( maybe '█' ("▁▂▃▄▅▆▇" !!)
lbounds = ((mn +) . (w *)) <$> [1 .. 7]
in fmap (maybe '█' ("▁▂▃▄▅▆▇" !!) . flip findIndex lbounds . flip (>)) xs
. (<)
 
)
parseFloats :: String -> [Float]
xxs
parseFloats = fmap read . filter (not . null) . splitOneOf " ,"
where
(mn, mx) = foldr (bimap . min <*> max) (x, x) xs
w = (mx - mn) / 8
lbounds = (mn +) . (w *) <$> [1 .. 7]
 
--------------------------- TEST -------------------------
main :: IO ()
main =
mapM_ putStrLn $
sparkLine . parseFloats
putStrLn
<$> [ "0, 1, 19, 20",
((sparkLine . parseFloats) <$>
[ "0, 1999, 194000, 204999, 7000, 7999",
, "0,1 999,2 4000,3 4999,4 7000,5 79996 7 8 7 6 5 4 3 2 1",
, "1 2 3 4 5 6 7"1.5, 80.5 73.5, 62.5 5.5, 4.5 37.5, 2 16.5"
, "1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5"]
 
])</lang>
parseFloats :: String -> [Float]
parseFloats =
fmap read
. filter (not . null)
. splitOneOf " ,"</syntaxhighlight>
{{Out}}
<pre>▁▁██
Line 1,024 ⟶ 1,250:
 
=={{header|J}}==
'''Solution''' (''explicit''):<langsyntaxhighlight lang="j"> spkln =: verb define
y spkln~ 4 u:16b2581+i.8 NB. ▁▂▃▄▅▆▇█
:
Line 1,030 ⟶ 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 1,042 ⟶ 1,268:
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">
public class Sparkline
{
Line 1,084 ⟶ 1,310:
}
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,093 ⟶ 1,319:
 
</pre>
 
 
=={{header|JavaScript}}==
Line 1,099 ⟶ 1,324:
===ES6===
 
<langsyntaxhighlight JavaScriptlang="javascript">(() => {
'use strict';
 
Line 1,256 ⟶ 1,481:
// MAIN ---
return main();
})();</langsyntaxhighlight>
{{Out}}
<pre>▁▁██
Line 1,275 ⟶ 1,500:
 
=={{header|jq}}==
<langsyntaxhighlight lang="jq">def sparkline:
min as $min
| ( (max - $min) / 7 ) as $div
Line 1,283 ⟶ 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 1,294 ⟶ 1,519:
 
=={{header|Julia}}==
<syntaxhighlight lang="julia">function sparklineit(arr)
{{works with|Julia|0.6}}
 
<lang julia>function sparklineit(arr::Vector{<:Integer})
sparkchars = '\u2581':'\u2588'
dyn = length(sparkchars)
Line 1,307 ⟶ 1,530:
println("$v → ", sparklineit(v))
v = 10rand(10)
println("$(round.(v, 2)) → ", sparklineit(v))</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] → ▅▃█▄▁█▁▁▃▅
[0.57, 0.14, 4.73, 6.61, 6.9, 0.8, 9.71, 7.39, 2.75, 5.7] → ▁▁▄▆▆▁█▇▃▅</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] → ▂▁▄▃▆▅█▇</pre>
 
=={{header|Kotlin}}==
{{trans|Java}}
<langsyntaxhighlight lang="scala">internal const val bars = "▁▂▃▄▅▆▇█"
internal const val n = bars.length - 1
 
Line 1,336 ⟶ 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 1,344 ⟶ 1,575:
 
=={{header|LiveCode}}==
<langsyntaxhighlight LiveCodelang="livecode">command sparklines listOfNums
local utfbase=0x2581
local tStats, utfp, tmin,tmax,trange
Line 1,365 ⟶ 1,596:
end repeat
put plot
end sparklines</langsyntaxhighlight>
 
Test
Line 1,376 ⟶ 1,607:
▂▁▄▃▆▅█▇</pre>
 
=={{header|NetRexx}}==
<lang NetRexx>/* NetRexx */
options replace format comments java crossref symbols nobinary
 
runSample(arg)
return
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method sparkline(spark) private static
spark = spark.changestr(',', ' ')
bars = '\u2581 \u2582 \u2583 \u2584 \u2585 \u2586 \u2587 \u2588'
barK = bars.words()
nmin = spark.word(1)
nmax = nmin
-- get min & max values
loop iw = 1 to spark.words()
nval = spark.word(iw)
nmin = nval.min(nmin)
nmax = nval.max(nmax)
end iw
range = nmax - nmin + 1
slope = ''
loop iw = 1 to spark.words()
point = Math.ceil((spark.word(iw) - nmin + 1) / range * barK)
slope = slope || bars.word(point)
end iw
return slope nmin nmax range
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method runSample(arg) private static
-- sample data setup
parse arg vals
sparks = 0
sparks[0] = 0
if vals = '' then do
si = sparks[0] + 1; sparks[0] = si; sparks[si] = 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
si = sparks[0] + 1; sparks[0] = si; sparks[si] = '1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5'
end
else do
loop until vals = ''
-- split input on a ! character
parse vals lst '!' vals
si = sparks[0] + 1; sparks[0] = si; sparks[si] = lst
end
end
-- run the samples
loop si = 1 to sparks[0]
vals = sparks[si]
parse sparkline(vals) slope .
say 'Input: ' vals
say 'Sparkline: ' slope
say
end si
return
</lang>
{{out}}
<pre>
Input: 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
Sparkline: ▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
 
Input: 1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5
Sparkline: ▂▁▄▃▆▅█▇
</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.
Line 1,448 ⟶ 1,615:
 
 
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module CheckIt {
Function Row$(a) {
Line 1,483 ⟶ 1,650:
}
Checkit
</syntaxhighlight>
</lang>
 
Function Param() get a string an put it as inline code in expressions
 
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module CheckIt {
Font "Dejavu Sans Mono"
Line 1,515 ⟶ 1,682:
}
Checkit
</syntaxhighlight>
</lang>
 
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">
<lang M2000 Interpreter>
Module CheckIt {
Function ExtractDat(dat$) {
Line 1,553 ⟶ 1,720:
}
Checkit
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,562 ⟶ 1,729:
</pre >
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">toSparkline[data_String] := FromCharacterCode[Round[7 Rescale@Flatten@ImportString[data, "Table", "FieldSeparators" -> {" ", ","}]] + 16^^2581];</langsyntaxhighlight>
<pre>
toSparkline["1 2 3 4 5 6 7 8 7 6 5,4 3 2 1 "]
Line 1,570 ⟶ 1,737:
toSparkline[" 1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5 "]
▂▁▄▃▆▅█▇
</pre>
 
=={{header|NetRexx}}==
<syntaxhighlight lang="netrexx">/* NetRexx */
options replace format comments java crossref symbols nobinary
 
runSample(arg)
return
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method sparkline(spark) private static
spark = spark.changestr(',', ' ')
bars = '\u2581 \u2582 \u2583 \u2584 \u2585 \u2586 \u2587 \u2588'
barK = bars.words()
nmin = spark.word(1)
nmax = nmin
-- get min & max values
loop iw = 1 to spark.words()
nval = spark.word(iw)
nmin = nval.min(nmin)
nmax = nval.max(nmax)
end iw
range = nmax - nmin + 1
slope = ''
loop iw = 1 to spark.words()
point = Math.ceil((spark.word(iw) - nmin + 1) / range * barK)
slope = slope || bars.word(point)
end iw
return slope nmin nmax range
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method runSample(arg) private static
-- sample data setup
parse arg vals
sparks = 0
sparks[0] = 0
if vals = '' then do
si = sparks[0] + 1; sparks[0] = si; sparks[si] = 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
si = sparks[0] + 1; sparks[0] = si; sparks[si] = '1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5'
end
else do
loop until vals = ''
-- split input on a ! character
parse vals lst '!' vals
si = sparks[0] + 1; sparks[0] = si; sparks[si] = lst
end
end
-- run the samples
loop si = 1 to sparks[0]
vals = sparks[si]
parse sparkline(vals) slope .
say 'Input: ' vals
say 'Sparkline: ' slope
say
end si
return
</syntaxhighlight>
{{out}}
<pre>
Input: 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
Sparkline: ▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
 
Input: 1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5
Sparkline: ▂▁▄▃▆▅█▇
</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,588 ⟶ 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,599 ⟶ 1,831:
min: 0.5; max: 7.5
▂▁▄▃▆▅█▇</pre>
 
=={{header|OCaml}}==
<syntaxhighlight lang="ocaml">let before_first_bar = 0x2580
let num_bars = 8
 
let sparkline numbers =
let max_num = List.fold_left max 0. numbers in
let scale = float_of_int num_bars /. max_num in
let bars = Buffer.create num_bars in
let add_bar number =
let scaled = scale *. number |> Float.round |> int_of_float in
if scaled <= 0 then
(* Using underscore character to differentiate between zero and one *)
Buffer.add_char bars '_'
else
scaled + before_first_bar |> Uchar.of_int |> Buffer.add_utf_8_uchar bars
in
List.iter add_bar numbers;
Buffer.contents bars
 
let print_sparkline line =
Printf.printf "Numbers: %s\n" line;
line
|> String.trim
|> 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: 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:
1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5
▂▁▄▃▆▅█▇
</pre>
 
=={{header|Perl}}==
<langsyntaxhighlight 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;
Line 1,630 ⟶ 1,918:
# one sparkline per line
print sparkline( split /[\s,]+/ ) while <>;
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,670 ⟶ 1,958:
8 values; range -8e+307..-1e+307
█▇▆▅▄▃▂▁</pre>
 
=={{header|Perl 6}}==
<lang perl6>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;
}</lang>
{{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
▂▁▄▃▆▅█▇
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|Phix}}==
Works fine on Linux, with or without unicode_console.e as that does little apart from check environment settings for clues, but on my windowsWindows 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) improvedimproves things considerably - suggestions welcome.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>include builtins\unicode_console.e -- (0.8.0+)
<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>
constant tests = {"0 1 19 20", "0 0 1 1",
<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>
"0 999 4000 4999 7000 7999", "1 1 2 2 3 3",
"1 2 3 4 5 6 7 8 7 6 5 4 3 2 1",
<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>
"1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5"}
<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>
for i=1 to length(tests) do
<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>
sequence ti = split_any(tests[i]," ,",no_empty:=true)
for j=1 to length(ti) do
<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>
{{ti[j]}} = scanf(ti[j],"%f")
<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>
end for
<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>
atom mn = min(ti),
<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>
mx = max(ti),
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
range = mx-mn
<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>
printf(1,"Min :%g, Max :%g, Range :%g\n",{mn,mx,range})
<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>
if unicode_console() then
<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>
for j=1 to length(ti) do
ti[j] = #2581 + min(7,floor((ti[j]-mn)/range*8))
<span style="color: #008080;">if</span> <span style="color: #000000;">unicode_console</span><span style="color: #0000FF;">()</span> <span style="color: #008080;">then</span>
end for
<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>
printf(1,"%s\n",{utf32_to_utf8(ti)})
<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>
else
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
puts(1,"unicode is not supported\n")
<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>
end if
<span style="color: #008080;">else</span>
end for</lang>
<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>
Line 1,738 ⟶ 2,008:
 
=={{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,752 ⟶ 2,022:
 
=={{header|Python}}==
<langsyntaxhighlight lang="python"># -*- coding: utf-8 -*-
 
# Unicode: 9601, 9602, 9603, 9604, 9605, 9606, 9607, 9608
Line 1,776 ⟶ 2,046:
mn, mx, sp = sparkline(numbers)
print(' min: %5f; max: %5f' % (mn, mx))
print(" " + sp)</langsyntaxhighlight>
 
{{out}}
Line 1,808 ⟶ 2,078:
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'''
<lang python>import re
 
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)
Line 1,822 ⟶ 2,101:
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)),
lambda x: maybe('█')(
lambda i: '▁▂▃▄▅▆▇'[i]
)(findIndex(lambda b: b > x)(lbounds)),
xs
)),
' '.join(map(str, xs)),
'\t'.join([
Line 1,845 ⟶ 2,128:
 
 
# -------------------------- TEST --------------------------
# main :: IO ()
def main():
'''Tested on some sample lists.
for x in map(
'''
lambda s: sparkLine(readFloats(s)),
[print(
"0, 1, 19, 20",unlines(map(
"0compose(compose(unlines, 999sparkLine), 4000, 4999, 7000, 7999"readFloats),
"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"0, 4.51, 7.519, 6.520",
"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"
print ('\n'.join(x))
]
 
))
)
 
# GENERIC -------------------------------------------------
 
# ------------------------ 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}
 
Line 1,869 ⟶ 2,158:
# 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
 
Line 1,879 ⟶ 2,194:
# 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:
Line 1,886 ⟶ 2,205:
except StopIteration:
return Nothing()
return lambda xs: go(xs)
 
 
# maybe :: b -> (a -> b) -> Maybe a -> b
def maybe(v):
return'''Either lambdathe f:default lambda m:value v, if m.get('Nothing') elseis (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
def mean(xs):
'''The arithmetic mean of the numeric
values in xs.
'''
return sum(xs) / float(len(xs))
 
Line 1,903 ⟶ 2,229:
# 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
# TEST -------------------------------------------------
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()</langsyntaxhighlight>
{{Out}}
<pre>▁▁██
Line 1,928 ⟶ 2,266:
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
▂▁▄▃▆▅█▇
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,934 ⟶ 2,353:
{{Works with|ooRexx}}
{{Works with|Regina|3.4}}
<langsyntaxhighlight REXXlang="rexx">/* Rexx */
 
parse arg aaa
Line 2,001 ⟶ 2,420:
return
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 2,026 ⟶ 2,445:
 
It should also be noted that the CMS and TSO versions of REXX (and practically all others) don't support ''single line comments''.
<langsyntaxhighlight lang="rexx">/*REXX program displays a sparkline (spark graph) for a group of values. */
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
Line 2,050 ⟶ 2,469:
end /*j*/
 
say 'output: ' z; say; return /*show the output, + a blank line*/</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
Line 2,059 ⟶ 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 2,091 ⟶ 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 2,118 ⟶ 2,515:
 
=={{header|Rust}}==
<langsyntaxhighlight lang="rust">
const BARS: &'static str = "▁▂▃▄▅▆▇█";
 
Line 2,136 ⟶ 2,533:
print_sparkline(s2);
}
</syntaxhighlight>
</lang>
{{out}}
"▁▂▃▄▅▆▇█▇▆▅▄▃▂▁"
Line 2,143 ⟶ 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 2,169 ⟶ 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 2,176 ⟶ 2,573:
 
=={{header|Scala}}==
<langsyntaxhighlight lang="scala">def mkSparks( numStr:String ) : String =
numStr.split( "[\\s,]+" ).map(_.toFloat) match {
case v if v.isEmpty => ""
Line 2,191 ⟶ 2,588:
 
// A random test...
println( mkSparks( Stream.continually( math.abs(util.Random.nextInt % 8)).take(64).mkString(" ") ))</langsyntaxhighlight>
{{out}}
<pre> ▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
Line 2,198 ⟶ 2,595:
 
=={{header|Seed7}}==
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "scanfile.s7i";
include "float.s7i";
Line 2,250 ⟶ 2,647:
data := readDataLine;
end while;
end func;</langsyntaxhighlight>
 
{{out}}
Line 2,259 ⟶ 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 2,271 ⟶ 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 2,282 ⟶ 2,709:
=={{header|Tcl}}==
{{works with|Tcl|8.6}}
<langsyntaxhighlight lang="tcl">package require Tcl 8.6
 
proc extractValues {series} {
Line 2,296 ⟶ 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 2,305 ⟶ 2,732:
puts "Series: $series"
puts "Sparkline: [sparkline $series]"
}</langsyntaxhighlight>
{{out}}
<pre>
Line 2,312 ⟶ 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 2,323 ⟶ 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 2,334 ⟶ 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,476

edits