Peter
Peter Campbell Smith

Ordinal sparkles

Weekly challenge 179 — 22 August 2022

Week 179: 22 Aug 2022

Task 2

Task — Unicode sparkline

You are given a list of positive numbers, @n. Write a script to print a sparkline in Unicode for the given list of numbers.

Analysis

A sparkline is a small graph, shown without axes, demonstrating visually the variation in some quantity. We are to use the Unicode characters 0x2581 to 0x2588 - ▁ ▂ ▃ ▄ ▅ ▆ ▇ █.

It isn't stated explicitly, but I have assumed we are to divide the presented numbers amongst some number - I've assumed 10 - equally sized buckets such that the smallest member of @n is in the first bucket and the greatest is in the last.

So the process is:

  • Find the least and greatest of the elements of $n
  • Divide the difference between those by 10: this is the 'width' of each bucket
  • Count the number of elements of $n which fall into each bucket
  • Scale these counts such that the smallest is 1 and the largest
    is 8
  • Use these counts to create a sparkline with the 8 Unicode characters

Note: The representation of the Unicode characters varies a lot from font to font so I have supplied the numeric values representing the heights of the 8 characters in the sparkline.

Try it 

Try running the script with any input. Rather than asking you to input a lot of numbers, enter a number between 10 and 500 and that number of randomised numbers will be generated for you.



example: 100

Script


#!/usr/bin/perl

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

use v5.26;    # The Weekly Challenge - 2022-08-22
use utf8;     # Week 179 - task 2 - Unicode sparkline
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';

my @values;
push @values, int(rand(50) + 10) for 0 .. 50;
unicode_sparkline(@values);

sub unicode_sparkline {
    
    my (@input, @symbols, $range, $group, $value, $n, @buckets, $sparkline, $max_bucket, $min_bucket, $m,
        $digitline, @digits);
    
    @input = sort {$a <=> $b} @_;
    @symbols = qw(▁ ▂ ▃ ▄ ▅ ▆ ▇ █);
    @digits = qw(1 2 3 4 5 6 7 8);
    @buckets = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
    
    # divide input values into 10 buckets of equal width
    $range = ($input[-1] - $input[0]) * 1.001;
    $group = $range / 10;

    $max_bucket = 0;
    for $value (@input) {
        $n = int(($value - $input[0]) / $group);
        $buckets[$n] ++;
        $max_bucket = $buckets[$n] if $buckets[$n] > $max_bucket;
    }
    $min_bucket = $max_bucket;
    for $n (0 .. 9) {
        $min_bucket = $buckets[$n] if $buckets[$n] < $min_bucket;
    }

    # scale vertical 1 to 8
    for $n (0 .. 9) {
        $m = int(($buckets[$n] - $min_bucket) / ($max_bucket - $min_bucket) * 7.999);
        $sparkline .= qq[$symbols[$m]];
        $digitline .= qq[$digits[$m]];
    }
        
    say qq[\nInput:  \@n = (] . join(', ', @_) . ')';
    say qq[Output: $sparkline (values are $digitline)];
}

Output


Input:  @n = (41, 58, 54, 27, 55, 13, 17, 41, 18, 20, 16,
43, 45, 58, 44, 34, 30, 27, 27, 55, 57, 32, 52, 44, 35,
49, 19, 40, 58, 10, 52, 34, 53, 22, 57, 54, 26, 28, 13,
56, 41, 50, 44, 27, 13, 10, 55, 59, 25, 51, 50)
Output: ▄▃▁▆▃▁▇▁▇█ (values are 4316317178)

 

Any content of this website which has been created by Peter Campbell Smith is in the public domain