aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Thompson <i@ry.ca>2020-02-25 16:47:48 -0600
committerRyan Thompson <i@ry.ca>2020-02-25 16:47:48 -0600
commit313e8c3d90a1b6785e5c4ca3b3c9e42d0533de47 (patch)
treec10f10c1ba7f834bf0e2caed0510f77bf1d9aac8
parent29183b30851f09a0975cd4898a9d3ebe503568ff (diff)
downloadperlweeklychallenge-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.rakumod85
-rw-r--r--challenge-047/arne-sommer/raku/lib/Number/Roman/OO.rakumod67
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));
+}