diff options
| author | Luca Ferrari <fluca1978@gmail.com> | 2020-02-10 10:16:26 +0100 |
|---|---|---|
| committer | Luca Ferrari <fluca1978@gmail.com> | 2020-02-10 10:16:26 +0100 |
| commit | ea32be64d34ed2a25cfdb3167dee07e4dbc5c6ce (patch) | |
| tree | 82b119cb88969ba5679436b195b71be255236305 /challenge-047 | |
| parent | 928598617a6aa7e29c0e1317bf402ddef4419828 (diff) | |
| download | perlweeklychallenge-club-ea32be64d34ed2a25cfdb3167dee07e4dbc5c6ce.tar.gz perlweeklychallenge-club-ea32be64d34ed2a25cfdb3167dee07e4dbc5c6ce.tar.bz2 perlweeklychallenge-club-ea32be64d34ed2a25cfdb3167dee07e4dbc5c6ce.zip | |
First task done.
Diffstat (limited to 'challenge-047')
| -rw-r--r-- | challenge-047/luca-ferrari/raku/ch-1.p6 | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/challenge-047/luca-ferrari/raku/ch-1.p6 b/challenge-047/luca-ferrari/raku/ch-1.p6 new file mode 100644 index 0000000000..789127c5e9 --- /dev/null +++ b/challenge-047/luca-ferrari/raku/ch-1.p6 @@ -0,0 +1,92 @@ +#!env raku +# +# Perl Weekly Challenge 47 +# see <https://perlweeklychallenge.org/blog/perl-weekly-challenge-047/> +# +# Task 1 +# Roman Calculator +# Write a script that accepts two roman numbers and operation. +# It should then perform the operation on the give +# roman numbers and print the result. +# For example, +# perl ch-1.pl V + VI +# It should print +# XI +# +# +# Example of output +# % raku ch-1.p6 V + IX +# XIV + + +my %roman-to-arabic = :I(1), :V(5), :X(10), :L(50), :C(100), :D(500), :M(1000); + + +# Function to convert a roman number into an arabic one. +sub convert-roman-to-arabic( Str:D $roman ) { + # convert to uppercase, reverse the string + # and translates into numbers. For example, + # IX => [ 10 1 ] + # then map so that the current value is multiplied by -1 if the + # previous one is higher + my @arabic-digits = $roman.uc.comb.reverse.map: { + state $last = 0; + my $value = %roman-to-arabic{ $_ }; + $value *= -1 if $value < $last; + $last = $value; + $value; + }; + + return [+] @arabic-digits; +} + + +# Function to convert an arabic number into a roman one. +sub convert-arabic-to-roman( Int $arabic ) { + + # special cases: what to subtract from every value + my %subtractors = 1_000 => 100, + 500 => 100, + 100 => 10, + 50 => 10, + 10 => 1, + 5 => 1, + 1 => 0; + + # reverse the map of the values so that each arabic value + # corresponds to a letter + my %translator = %roman-to-arabic.map( { $_.value => $_.key } ); + + + return '' if ! $arabic; + + for %subtractors.pairs.sort: { $^b.key.Int <=> $^a.key.Int } -> $pair { + my $subtractor = $pair.key.Int; + my $removing = $pair.value.Int; + + return %translator{ $subtractor } ~ convert-arabic-to-roman( $arabic - $subtractor.Int ) if $arabic >= $subtractor; + return %translator{ $removing } ~ convert-arabic-to-roman( $arabic + $removing.Int ) if $arabic >= $subtractor - $removing; + + } + +} + + + +######################################## +# Main program +######################################## + +die "Usage: $*PROGRAM <operand> <operator> <operand>" if @*ARGS.elems != 3; + +my $operand-a = convert-roman-to-arabic( @*ARGS[0] ); +my $operand-b = convert-roman-to-arabic( @*ARGS[2] ); + +my $result = do given @*ARGS[1].trim { + when '+' { $operand-a + $operand-b; } + when '-' { $operand-a - $operand-b; } + when '/' { $operand-a / $operand-b; } + when '*' { $operand-a * $operand-b; } +}; + +say convert-arabic-to-roman( $result ); |
