Fun with Perl 6 using Roman Numerals

Daniel Mita
Jun 1 · 4 min read

Defining The Numerals

constant @letters   = 「IVXLCDM」.comb;
constant @overlines = "\c[combining overline]", "\c[combining double overline]"; # These represent x 1000 and x 1000000
constant @letter-pairs = reverse # … the following code
@letters[0], |( @letters, |@overlines.map( @letters X~ * ) ).map({
gather {
for .rotor(3 => -1) -> @group {
for 1, 2 {
take @group[0, $_].join;
take @group[$_];
}
}
}
}).flat;
@letters, |@overlines.map( @letters X~ * )
# (I V X L C D M)(I̅ V̅ X̅ L̅ C̅ D̅ M̅)(I̿ V̿ X̿ L̿ C̿ D̿ M̿)
.rotor(3 => -1)
# ((I V X) (X L C) (C D M))
# .[0,1], .[1], .[0,2], .[2] on each group gives us IV, V, IX, X etc
1, |( * X* 4, 5, 9, 10 ) … ∞
:I(1), :IV(4), :V(5), :IX(9), :X(10), :XL(40) …

Converting Numbers to Roman Numerals

given %(@letter-pairs.Map.antipairs) -> %letter-map {
return [~] gather {
for $number.flip.comb.pairs.reverse {
given 10 ** .key -> $key {
when .value == 4 | 9 {
take %letter-map{ $key * .value };
}
take %letter-map{ $key * 5 } if .value ≥ 5;
take %letter-map{ $key } x .value % 5;
}
}
};
}
12345.flip.comb.pairs.reverse
# 4 => 1, 3 => 2, 2 => 3, 1 => 4, 0 => 5
when .value == 4 | 9 {
take %letter-map{ $key * .value };
}
take %letter-map{ $key * 5 } if .value ≥ 5;
take %letter-map{ $key } x .value % 5;
}

Converting Roman Numerals to Numbers

return [+] gather {
my $str = $roman-string.uc;
for @letter-pairs -> $pair {
if $str ~~ / ^ ( $($pair.key) )+ / {
take ($pair.value xx $0).Slip;
$str.=substr($0.join.chars);
}
}
}
Daniel Mita

Written by

I am a professional Perl programmer, and in my spare time I do mentoring and maintenance for the Perl 5 and 6 tracks on https://exercism.io/

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade