Cistercian numerals

Handles 0 through 9999 only. No error trapping. If you feed it an unsupported number it will truncate to maximum 4 digits.

my @line-segments = (0, 0, 0, 100),
    (0,  0, 35,  0), (0, 35, 35, 35), (0,  0, 35, 35), (0, 35, 35,  0), ( 35,  0, 35, 35),
    (0,  0,-35,  0), (0, 35,-35, 35), (0,  0,-35, 35), (0, 35,-35,  0), (-35,  0,-35, 35),
    (0,100, 35,100), (0, 65, 35, 65), (0,100, 35, 65), (0, 65, 35,100), ( 35, 65, 35,100),
    (0,100,-35,100), (0, 65,-35, 65), (0,100,-35, 65), (0, 65,-35,100), (-35, 65,-35,100);

my @components = map {@line-segments[$_]}, |((0, 5, 10, 15).map: -> $m {
    |((0,), (1,), (2,), (3,), (4,), (1,4), (5,), (1,5), (2,5), (1,2,5)).map: {$_ »+» $m}
});

my $out = 'Cistercian-raku.svg'.IO.open(:w);

$out.say: # insert header
q|<svg  width="875" height="470" style="stroke:black;" version="1.1" xmlns="https://www.w3.org/2000/svg">
 <rect width="100%" height="100%" style="fill:white;"/>|;

my $hs = 50; # horizontal spacing
my $vs = 25; # vertical spacing

for flat ^10, 20, 300, 4000, 5555, 6789, 9394, (^10000).pick(14) -> $cistercian {

    $out.say: |@components[0].map: { # draw zero / base vertical bar
        qq|<line x1="{.[0] + $hs}" y1="{.[1] + $vs}" x2="{.[2] + $hs}" y2="{.[3] + $vs}"/>|
    };

    my @orders-of-magnitude = $cistercian.polymod(10 xx *);

    for @orders-of-magnitude.kv -> $order, $value {
        next unless $value; # skip zeros, already drew zero bar
        last if $order > 3; # truncate too large integers

        # draw the component line segments
        $out.say: join "\n", @components[$order * 10 + $value].map: {
            qq|<line x1="{.[0] + $hs}" y1="{.[1] + $vs}" x2="{.[2] + $hs}" y2="{.[3] + $vs}"/>|
        }
    }

    # insert the decimal number below
    $out.say: qq|<text x="{$hs - 5}" y="{$vs + 120}">{$cistercian}</text>|;

    if ++$ %% 10 { # next row
        $hs = -35;
        $vs += 150;
    }

    $hs += 85; # increment horizontal spacing


}
$out.say: q|</svg>|; # insert footer

Last updated