diff options
| author | Ryan Thompson <i@ry.ca> | 2020-02-25 16:47:48 -0600 |
|---|---|---|
| committer | Ryan Thompson <i@ry.ca> | 2020-02-25 16:47:48 -0600 |
| commit | 313e8c3d90a1b6785e5c4ca3b3c9e42d0533de47 (patch) | |
| tree | c10f10c1ba7f834bf0e2caed0510f77bf1d9aac8 | |
| parent | 29183b30851f09a0975cd4898a9d3ebe503568ff (diff) | |
| download | perlweeklychallenge-club-313e8c3d90a1b6785e5c4ca3b3c9e42d0533de47.tar.gz perlweeklychallenge-club-313e8c3d90a1b6785e5c4ca3b3c9e42d0533de47.tar.bz2 perlweeklychallenge-club-313e8c3d90a1b6785e5c4ca3b3c9e42d0533de47.zip | |
Add lib/ at Arne's request
Source: https://raku-musings.com/code/roman-gap.zip
Page: https://raku-musings.com/roman-gap.html
| -rw-r--r-- | challenge-047/arne-sommer/raku/lib/Number/Roman.rakumod | 85 | ||||
| -rw-r--r-- | challenge-047/arne-sommer/raku/lib/Number/Roman/OO.rakumod | 67 |
2 files changed, 152 insertions, 0 deletions
diff --git a/challenge-047/arne-sommer/raku/lib/Number/Roman.rakumod b/challenge-047/arne-sommer/raku/lib/Number/Roman.rakumod new file mode 100644 index 0000000000..1196448d6a --- /dev/null +++ b/challenge-047/arne-sommer/raku/lib/Number/Roman.rakumod @@ -0,0 +1,85 @@ +use v6; +use MONKEY-TYPING; + +unit module Number::Roman; + +our sub to-roman (Int $number is copy) is export(:to) +{ + my $string = ""; + + while $number >= 1000 { $string ~= "M"; $number -= 1000; } + if $number >= 900 { $string ~= "CM"; $number -= 900; } + if $number >= 500 { $string ~= "D"; $number -= 500; } + if $number >= 400 { $string ~= "CD"; $number -= 400; } + while $number >= 100 { $string ~= "C"; $number -= 100; } + if $number >= 90 { $string ~= "XC"; $number -= 90; } + if $number >= 50 { $string ~= "L"; $number -= 50; } + if $number >= 40 { $string ~= "XL"; $number -= 40; } + while $number >= 10 { $string ~= "X"; $number -= 10; } + if $number >= 9 { $string ~= "IX"; $number -= 9; } + if $number >= 5 { $string ~= "V"; $number -= 5; } + if $number >= 4 { $string ~= "IV"; $number -= 4; } + while $number >= 1 { $string ~= "I"; $number -= 1; } + + return $string; +} + +my %value = (I => 1, V => 5, X => 10, L => 50, C => 100, D => 500, M => 1000); + +my Set $valid-roman = %value.keys.Set; + +my $current-value = Inf; + +our sub from-roman (Str $roman) is export(:from) +{ + my @digits = $roman.comb; + + die "Non-Roman digit $_ detected." unless $valid-roman{$_} for @digits; + + my $number = 0; + + while @digits + { + my $current = @digits.shift; + + if @digits.elems + { + if %value{@digits[0]} > %value{$current} + { + $number += %value{@digits.shift} - %value{$current}; + next; + } + } + $number += %value{$current}; + } + + return to-roman($number) eq $roman + ?? $number + !! die "Not a valid Roman Number: $roman"; +} + +augment class Int +{ + method roman + { + return to-roman(self); + } + + multi method base ("r") + { + return self.roman; + } +} + +augment class Str +{ + method from-roman + { + return from-roman(self); + } + + multi method parse-base ("r") + { + return self.from-roman; + } +} diff --git a/challenge-047/arne-sommer/raku/lib/Number/Roman/OO.rakumod b/challenge-047/arne-sommer/raku/lib/Number/Roman/OO.rakumod new file mode 100644 index 0000000000..a8bcda0733 --- /dev/null +++ b/challenge-047/arne-sommer/raku/lib/Number/Roman/OO.rakumod @@ -0,0 +1,67 @@ +use v6; + +use Number::Roman :to, :from; + +unit class Number::Roman::OO; + +has Int $.value; + +multi method new (Str $string) { self.bless(value => from-roman($string)) } +multi method new($value) { self.bless(:$value) } + +multi method add (Number::Roman::OO:D $obj) { return self.new(self.value + $obj.Int) } +multi method add (Int $int) { return self.new(self.value - $int) } + +multi method sub (Number::Roman::OO:D $obj) { return self.new(self.value + $obj.Int) } +multi method sub (Int $int) { return self.new(self.value - $int) } + +multi method mul (Number::Roman::OO:D $obj) { return self.new(self.value * $obj.Int) } +multi method mul (Int $int) { return self.new(self.value * $int) } + +multi method div (Number::Roman::OO:D $obj) { return self.new(Int(self.value / $obj.Int)) } +multi method div (Int $int) { return self.new(Int(self.value / $int)) } + +method Str { to-roman(self.value) } +method gist { to-roman(self.value) } +method Int { self.value } +method Real { self.value } + +multi sub infix:<+> (Number::Roman::OO:D $a, Number::Roman::OO:D $b) is export +{ + Number::Roman::OO.new($a.Int + $b.Int); +} + +multi sub infix:<+> (Number::Roman::OO:D $a, Int:D $b) +{ + Number::Roman::OO.new($a.Int + $b); +} + +multi sub infix:<-> (Number::Roman::OO:D $a, Number::Roman::OO:D $b) is export +{ + Number::Roman::OO.new($a.Int - $b.Int); +} + +multi sub infix:<-> (Number::Roman::OO:D $a, Int:D $b) +{ + Number::Roman::OO.new($a.Int - $b); +} + +multi sub infix:<*> (Number::Roman::OO:D $a, Number::Roman::OO:D $b) is export +{ + Number::Roman::OO.new($a.Int * $b.Int); +} + +multi sub infix:<*> (Number::Roman::OO:D $a, Int:D $b) +{ + Number::Roman::OO.new($a.Int * $b); +} + +multi sub infix:</> (Number::Roman::OO:D $a, Number::Roman::OO:D $b) is export +{ + Number::Roman::OO.new(Int($a.Int / $b.Int)); +} + +multi sub infix:</> (Number::Roman::OO:D $a, Int:D $b) +{ + Number::Roman::OO.new(Int($a.Int / $b)); +} |
