|
#!/usr/bin/env perl |
|
|
|
use v5.20; |
|
|
|
use Test::More; |
|
|
|
our %numerals = ( |
|
1 => "I", |
|
5 => "V", |
|
10 => "X", |
|
50 => "L", |
|
100 => "C", |
|
500 => "D", |
|
1000 => "M" |
|
); |
|
|
|
our @radix = sort {$a <=> $b} keys %numerals; |
|
|
|
our @bases = @radix[2, 4, 6]; |
|
|
|
sub to_roman { |
|
my $number = shift; |
|
|
|
# say "Working on $number"; |
|
my $smaller = shift [reverse grep {$_ < $number} @radix]; |
|
|
|
if(defined $numerals{$number}) { |
|
return $numerals{$number}; |
|
} |
|
elsif(defined $numerals{$number+100}) { |
|
return 'C' . $numerals{$number+100}; |
|
} |
|
elsif(defined $numerals{$number+10}) { |
|
return 'X' . $numerals{$number+10}; |
|
} |
|
elsif(defined $numerals{$number+1} ) { |
|
return 'I' . $numerals{$number+1}; |
|
} |
|
elsif($number < 4) { |
|
return "I" x $number; |
|
} |
|
|
|
return $numerals{$smaller} . to_roman($number - $smaller); |
|
} |
|
|
|
sub subtraction { |
|
my $number = shift; |
|
my $base = base($number); |
|
|
|
my $base_roman = to_roman($base); |
|
|
|
my @radix = keys %numerals; |
|
my $smaller_radix = [grep { $_ < $number} @radix]; |
|
# say "smaller_radix: @$smaller_radix"; |
|
my $smaller = $smaller_radix->[-2]; |
|
# say "smaller: $smaller"; |
|
|
|
# $number = 99 |
|
# $base = 100 |
|
# $smaller = 10 |
|
# $base - $smaller = 90 |
|
|
|
return to_roman($base - $smaller) . to_roman($number - ($base - $smaller)); |
|
} |
|
|
|
sub base { |
|
my $number = shift; |
|
my $larger = shift [grep {$_ > $number} @radix]; |
|
return $larger; |
|
} |
|
|
|
# for my $n (1..50) { |
|
# say to_roman($n); |
|
# } |
|
|
|
is to_roman(1), "I", "Simple 1 works"; |
|
is to_roman(2), "II", "Real simple 2 works"; |
|
is to_roman(4), "IV", "We have prepended values!"; |
|
is to_roman(5), "V", "We have Vs"; |
|
is to_roman(17), "XVII", "seventeen and stuff"; |
|
is to_roman(19), "XIX", "nineteen and stuff"; |
|
is to_roman(20), "XX", "twenty and stuff"; |
|
is to_roman(40), "XL", "fourty and stuff"; |
|
is to_roman(41), "XLI", "fourty one"; |
|
is to_roman(49), "XLIX", "Fourty NINE"; |
|
is to_roman(90), "XC", "NINETY YO"; |
|
is to_roman(99), "XCIX", "NINETY NINE YO"; |
|
is base(41), 50, "base of 41 good"; |
|
is base(99), 100, "Got good base"; |
|
is subtraction(99), "XCIX", "Can do fancy subtraction"; |
|
|
|
done_testing; |