Update all new Tasks

This commit is contained in:
Ingy döt Net 2015-02-20 09:02:09 -05:00
parent 00a190b0a6
commit 91df62d461
5697 changed files with 93386 additions and 804 deletions

View file

@ -0,0 +1,19 @@
A [[wp:Sparkline|sparkline]] is a graph of successive values laid out horizontally
where the height of the line is proportional to the values in succession.
Use the following series of Unicode characters to create a program
that takes a series of numbers separated by one or more whitespace or comma characters
and generates a sparkline-type bar graph of the values on a single line of output.
The eight characters: '▁▂▃▄▅▆▇█'<br>
(Unicode values U+2581 through U+2588).
Use your program to show sparklines for the following input,
here on this page:
# 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
# 1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5
:(note the mix of separators in this second case)!
;Notes:
* A space is not part of the generated sparkline.
* The sparkline may be accompanied by simple statistics of the data such as its range.

View file

@ -0,0 +1,23 @@
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"]
Loop, % strings.MaxIndex()
{
SL := Sparklines(strings[A_Index])
MsgBox, % "Min: " SL["Min"] ", Max: " SL["Max"] ", Range: " SL["Rng"] "`n" SL["Chars"]
}
Sparklines(s)
{
s := RegexReplace(s, "[^\d\.]+", ",")
Loop, Parse, s, `,
{
Max := A_LoopField > Max ? A_LoopField : Max
Min := !Min ? Max : A_LoopField < Min ? A_LoopField : Min
}
Rng := Max - Min
Loop, Parse, s, `,
Chars .= Chr(0x2581 + Round(7 * (A_LoopField - Min) / Rng))
return, {"Min": Min, "Max": Max, "Rng": Rng, "Chars": Chars}
}

View file

@ -0,0 +1,68 @@
#include <iostream>
#include <sstream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <locale>
class Sparkline {
public:
Sparkline(std::wstring &cs) : charset( cs ){
}
virtual ~Sparkline(){
}
void print(std::string spark){
const char *delim = ", ";
std::vector<float> data;
// Get first non-delimiter
std::string::size_type last = spark.find_first_not_of(delim, 0);
// Get end of token
std::string::size_type pos = spark.find_first_of(delim, last);
while( pos != std::string::npos || last != std::string::npos ){
std::string tok = spark.substr(last, pos-last);
// Convert to float:
std::stringstream ss(tok);
float entry;
ss >> entry;
data.push_back( entry );
last = spark.find_first_not_of(delim, pos);
pos = spark.find_first_of(delim, last);
}
// Get range of dataset
float min = *std::min_element( data.begin(), data.end() );
float max = *std::max_element( data.begin(), data.end() );
float skip = (charset.length()-1) / (max - min);
std::wcout<<L"Min: "<<min<<L"; Max: "<<max<<L"; Range: "<<(max-min)<<std::endl;
std::vector<float>::const_iterator it;
for(it = data.begin(); it != data.end(); it++){
float v = ( (*it) - min ) * skip;
std::wcout<<charset[ (int)floor( v ) ];
}
std::wcout<<std::endl;
}
private:
std::wstring &charset;
};
int main( int argc, char **argv ){
std::wstring charset = L"\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588";
// Mainly just set up utf-8, so wcout won't narrow our characters.
std::locale::global(std::locale("en_US.utf8"));
Sparkline sl(charset);
sl.print("1 2 3 4 5 6 7 8 7 6 5 4 3 2 1");
sl.print("1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5");
return 0;
}

View file

@ -0,0 +1,16 @@
void main() {
import std.stdio, std.range, std.algorithm, std.conv,
std.string, std.regex;
"Numbers please separated by space/commas: ".write;
immutable numbers = readln
.strip
.splitter(r"[\s,]+".regex)
.array /**/
.to!(real[]);
immutable mm = numbers.reduce!(min, max);
writefln("min: %4f, max: %4f", mm[]);
immutable bars = iota(9601, 9609).map!(i => i.to!dchar).dtext;
immutable div = (mm[1] - mm[0]) / (bars.length - 1);
numbers.map!(n => bars[cast(int)((n - mm[0]) / div)]).writeln;
}

View file

@ -0,0 +1,8 @@
defmodule RC do
def sparkline(str) do
values = str |> String.split(~r/(,| )+/)
|> Enum.map(&(elem(Float.parse(&1), 0)))
{min, max} = {Enum.min(values), Enum.max(values)}
IO.puts Enum.map(values, &(round((&1 - min) / (max - min) * 7 + 0x2581)))
end
end

View file

@ -0,0 +1,6 @@
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)

View file

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

View file

@ -0,0 +1,74 @@
package main
import (
"bufio"
"errors"
"fmt"
"math"
"os"
"regexp"
"strconv"
"strings"
)
func main() {
fmt.Println("Numbers please separated by space/commas:")
sc := bufio.NewScanner(os.Stdin)
sc.Scan()
s, n, min, max, err := spark(sc.Text())
if err != nil {
fmt.Println(err)
return
}
if n == 1 {
fmt.Println("1 value =", min)
} else {
fmt.Println(n, "values. Min:", min, "Max:", max)
}
fmt.Println(s)
}
var sep = regexp.MustCompile(`[\s,]+`)
func spark(s0 string) (sp string, n int, min, max float64, err error) {
ss := sep.Split(s0, -1)
n = len(ss)
vs := make([]float64, n)
var v float64
min = math.Inf(1)
max = math.Inf(-1)
for i, s := range ss {
switch v, err = strconv.ParseFloat(s, 64); {
case err != nil:
case math.IsNaN(v):
err = errors.New("NaN not supported.")
case math.IsInf(v, 0):
err = errors.New("Inf not supported.")
default:
if v < min {
min = v
}
if v > max {
max = v
}
vs[i] = v
continue
}
return
}
if min == max {
sp = strings.Repeat("▄", n)
} else {
rs := make([]rune, n)
f := 8 / (max - min)
for j, v := range vs {
i := rune(f * (v - min))
if i > 7 {
i = 7
}
rs[j] = '▁' + i
}
sp = string(rs)
}
return
}

View file

@ -0,0 +1,6 @@
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 }) }

View file

@ -0,0 +1,4 @@
["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)}"
}

View file

@ -0,0 +1,39 @@
import Data.Char (chr)
import Data.List.Split (splitOneOf)
toSparkLine :: [Double] -> [Char]
toSparkLine xs = map cl xs
where
top = maximum xs
bot = minimum xs
range = top - bot
cl x = chr $ 0x2581 + round ((x - bot) / range * 7)
makeSparkLine :: String -> (String, Stats)
makeSparkLine xs = (toSparkLine parsed, stats parsed)
where parsed = map read $ filter (not . null) $ splitOneOf " ," xs
data Stats = Stats { minValue, maxValue, rangeOfValues :: Double,
numberOfValues :: Int }
instance Show Stats where
show (Stats mn mx r n) = "min: " ++ show mn ++ "; max: " ++ show mx ++
"; range: " ++ show r ++ "; no. of values: " ++ show n
stats :: [Double] -> Stats
stats xs = Stats { minValue = mn, maxValue = mx,
rangeOfValues = mx - mn, numberOfValues = length xs }
where
mn = minimum xs
mx = maximum xs
drawSparkLineWithStats :: String -> IO ()
drawSparkLineWithStats xs = putStrLn sp >> print st
where (sp, st) = makeSparkLine xs
main :: IO ()
main = mapM_ drawSparkLineWithStats
["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"]

View file

@ -0,0 +1,7 @@
spkln =: verb define
y spkln~ 4 u:16b2581+i.8 NB. ▁▂▃▄▅▆▇█
:
'MIN MAX' =. (<./ , >./) y
N =. # x
x {~ <. (N-1) * (y-MIN) % MAX-MIN
)

View file

@ -0,0 +1 @@
spkln =: (4 u:16b2581+i.8)&$: : ([ {~ <:@#@[ * ] (- % >./@[ - ]) <./@])

View file

@ -0,0 +1 @@
spkln =: (4 u:16b2581+i.8)&$: : ([ {~ ((* <:@#)~ ((- % (- >./))~ <./)))

View file

@ -0,0 +1,4 @@
spkln 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
▁▂▃▄▅▆▇█▇▆▅▄▃▂▁
spkln 1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5
▁▅█▆▅▃▂▇▄▅

View file

@ -0,0 +1,41 @@
public class Sparkline
{
String bars="▁▂▃▄▅▆▇█";
public static void main(String[] args)
{
Sparkline now=new Sparkline();
float[] arr={1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1};
now.display1D(arr);
System.out.println(now.getSparkline(arr));
float[] arr1={1.5f, 0.5f, 3.5f, 2.5f, 5.5f, 4.5f, 7.5f, 6.5f};
now.display1D(arr1);
System.out.println(now.getSparkline(arr1));
}
public void display1D(float[] arr)
{
for(int i=0;i<arr.length;i++)
System.out.print(arr[i]+" ");
System.out.println();
}
public String getSparkline(float[] arr)
{
float min=Integer.MAX_VALUE;
float max=Integer.MIN_VALUE;
for(int i=0;i<arr.length;i++)
{
if(arr[i]<min)
min=arr[i];
if(arr[i]>max)
max=arr[i];
}
float range=max-min;
int num=bars.length()-1;
String line="";
for(int i=0;i<arr.length;i++)
{
line+=bars.charAt((int)Math.ceil(((arr[i]-min)/range*num)));
}
return line;
}
}

View file

@ -0,0 +1 @@
toSparkline[data_String] := FromCharacterCode[Round[7 Rescale@Flatten@ImportString[data, "Table", "FieldSeparators" -> {" ", ","}]] + 16^^2581];

View file

@ -0,0 +1,54 @@
/* 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

View file

@ -0,0 +1,8 @@
constant @bars = '' ... '';
while prompt 'Numbers separated by anything: ' -> $_ {
my @numbers = map +*, .comb(/ '-'? \d+ ['.' \d+]? /);
my ($mn,$mx) = @numbers.minmax.bounds;
say "min: $mn.fmt('%5f'); max: $mx.fmt('%5f')";
my $div = ($mx - $mn) / (@bars - 1);
say @bars[ (@numbers X- $mn) X/ $div ].join;
}

View file

@ -0,0 +1,19 @@
binmode(STDOUT, ":utf8");
sub sparkline {
my $s = shift;
my @n = split(/[\s,]+/,$s);
return unless @n;
my($min,$max) = ($n[0],$n[0]);
for my $v (@n) { $min = $v if $v < $min; $max = $v if $v > $max; }
printf "min: %5f; max %5f\n", $min, $max;
my @bars = map { chr($_) } 0x2581 .. 0x2588;
my $div = ($max - $min) / $#bars;
print join("", map { $bars[$div ? ($_-$min) / $div : @bars/2] } @n), "\n";
1;
}
while (1) {
print "Numbers separated by spaces/commas: ";
exit unless sparkline(scalar(<>));
}

View file

@ -0,0 +1,17 @@
import re
try: raw_input
except: raw_input = input
# Unicode: 9601, 9602, 9603, 9604, 9605, 9606, 9607, 9608
try: bar = u'▁▂▃▄▅▆▇█'
except: bar = '▁▂▃▄▅▆▇█'
barcount = len(bar) - 1
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[int( (n - mn) / extent * barcount)]
for n in numbers)
print('min: %5f; max: %5f' % (mn, mx))
print(sparkline)

View file

@ -0,0 +1 @@
Data source: http://rosettacode.org/wiki/Sparkline_in_unicode

View file

@ -0,0 +1,67 @@
/* Rexx */
parse arg aaa
call runSample aaa
return
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sparkline:
procedure
parse arg spark
spark = changestr(',', spark, ' ')
bars = ' '
barK = words(bars)
nmin = word(spark, 1)
nmax = nmin
-- get min & max values
do iw = 1 to words(spark)
nval = word(spark, iw)
nmin = min(nval, nmin)
nmax = max(nval, nmax)
end iw
range = nmax - nmin + 1
slope = ''
do iw = 1 to words(spark)
point = ceiling((word(spark, iw) - nmin + 1) / range * barK)
slope = slope || word(bars, point)
end iw
return slope nmin nmax range
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ceiling:
procedure
parse arg ceil
return trunc(ceil) + (ceil > 0) * (ceil \= trunc(ceil))
floor:
procedure
parse arg flor
return trunc(flor) - (flor < 0) * (flor \= trunc(flor))
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
runSample:
procedure
-- 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
do until vals = ''
-- split input on a ! character
parse var vals lst '!' vals
si = sparks.0 + 1; sparks.0 = si; sparks.si = lst
end
end
-- run the samples
do si = 1 to sparks.0
vals = sparks.si
parse value sparkline(vals) with slope .
say 'Input: ' vals
say 'Sparkline: ' slope
say
end si
return

View file

@ -0,0 +1,26 @@
/*REXX program displays a sparkline (spark graph) for a group of values.*/
if arg()==0 then do /*No arguments? 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 done.*/
/*──────────────────────────────────CEIL subroutine─────────────────────*/
ceil: procedure; parse arg ?; _=trunc(?); return _+(?>0)*(?\=_)
/*──────────────────────────────────SPARKGRAPH subroutine───────────────*/
sparkGraph: procedure; parse arg x; say ' input: ' x /*echo values*/
x=translate(x, ' ', ",") /*remove any superfluous commas. */
$='' /*chars to be used for the graph.*/
xmin=word(x,1); 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)*length($)),1)
end /*j*/
say 'output: ' z; say /*show the output, + a blank line*/
return

View file

@ -0,0 +1,13 @@
#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")

View file

@ -0,0 +1,2 @@
"▁▂▃▄▅▆▇█▇▆▅▄▃▂▁"
"▂▁▄▃▆▅█▇"

View file

@ -0,0 +1,8 @@
bar = ('▁'..'█').to_a
loop {print 'Numbers please separated by space/commas: '
numbers = gets.split(/[\s,]+/).map(&:to_f)
min, max = numbers.minmax
puts "min: %5f; max: %5f"% [min, max]
div = (max - min) / (bar.size - 1)
puts min == max ? bar.last*numbers.size : numbers.map{|num| bar[((num - min) / div).to_i]}.join
}

View file

@ -0,0 +1,16 @@
def mkSparks( numStr:String ) : String =
numStr.split( "[\\s,]+" ).map(_.toFloat) match {
case v if v.isEmpty => ""
case v if v.length == 1 => "\u2581"
case v =>
(for( i <- v;
s = "\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588".toCharArray;
d = (v.max - v.min) / (s.length - 1)
) yield s( ((i - v.min) / d).toInt)).mkString
}
println( mkSparks( "1 2 3 4 5 6 7 8 7 6 5 4 3 2 1" ) )
println( mkSparks( "1.5, 0.5 3.5, 2.5 5.5, 4.5 7.5, 6.5" ) )
// A random test...
println( mkSparks( Stream.continually( math.abs(util.Random.nextInt % 8)).take(64).mkString(" ") ))

View file

@ -0,0 +1,53 @@
$ include "seed7_05.s7i";
include "scanfile.s7i";
include "float.s7i";
include "utf8.s7i";
const func array float: readDataLine is func
result
var array float: data is 0 times 0.0;
begin
write("Numbers separated by anything: ");
IN.bufferChar := getc(IN);
skipSpace(IN);
while IN.bufferChar <> '\n' do
data &:= float parse getNumber(IN);
skipSpace(IN);
if IN.bufferChar = ',' then
IN.bufferChar := getc(IN);
end if;
skipSpace(IN);
end while;
end func;
const proc: main is func
local
const string: bars is "▁▂▃▄▅▆▇█";
var array float: data is 0 times 0.0;
var float: min is 0.0;
var float: max is 0.0;
var float: number is 0.0;
var integer: index is 0;
begin
OUT := STD_UTF8_OUT;
data := readDataLine;
while length(data) >= 1 do
min := data[1];
max := data[1];
for number range data do
if number < min then
min := number;
end if;
if number > max then
max := number;
end if;
end for;
for number range data do
index := succ(min(trunc((number - min) * 8.0 / max), 7));
write(bars[index]);
end for;
writeln;
data := readDataLine;
end while;
end func;

View file

@ -0,0 +1,15 @@
package require Tcl 8.6
proc extractValues {series} {
return [regexp -all -inline {\d+(?:\.\d*)?|\.\d+} $series]
}
proc renderValue {min max value} {
set band [expr {int(8*($value-$min)/(($max-$min)*1.01))}]
return [format "%c" [expr {0x2581 + $band}]]
}
proc sparkline {series} {
set values [extractValues $series]
set min [tcl::mathfunc::min {*}$values]
set max [tcl::mathfunc::max {*}$values]
return [join [lmap v $values {renderValue $min $max $v}] ""]
}

View file

@ -0,0 +1,8 @@
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"
}
foreach series $data {
puts "Series: $series"
puts "Sparkline: [sparkline $series]"
}