aboutsummaryrefslogtreecommitdiff
path: root/challenge-227
diff options
context:
space:
mode:
authorMohammad S Anwar <mohammad.anwar@yahoo.com>2023-07-26 23:16:10 +0100
committerMohammad S Anwar <mohammad.anwar@yahoo.com>2023-07-26 23:16:10 +0100
commitf84f38be0e67c61c44fa0769b00e53124d1bdde0 (patch)
treeca3c2b5f833306b7d3b14abb77fda783cdf998cf /challenge-227
parent6a31bf4676dcb9f83b0ef2d91407301686ed0cd8 (diff)
downloadperlweeklychallenge-club-f84f38be0e67c61c44fa0769b00e53124d1bdde0.tar.gz
perlweeklychallenge-club-f84f38be0e67c61c44fa0769b00e53124d1bdde0.tar.bz2
perlweeklychallenge-club-f84f38be0e67c61c44fa0769b00e53124d1bdde0.zip
- Added solutions by Arne Sommer.
- Added solutions by Laurent Rosenfeld.
Diffstat (limited to 'challenge-227')
-rw-r--r--challenge-227/laurent-rosenfeld/blog1.txt1
-rw-r--r--challenge-227/laurent-rosenfeld/perl/ch-2.pl63
-rw-r--r--challenge-227/laurent-rosenfeld/raku/ch-2.raku57
3 files changed, 121 insertions, 0 deletions
diff --git a/challenge-227/laurent-rosenfeld/blog1.txt b/challenge-227/laurent-rosenfeld/blog1.txt
new file mode 100644
index 0000000000..66db4bdf8e
--- /dev/null
+++ b/challenge-227/laurent-rosenfeld/blog1.txt
@@ -0,0 +1 @@
+https://blogs.perl.org/users/laurent_r/2023/07/perl-weekly-challenge-227-roman-maths.html
diff --git a/challenge-227/laurent-rosenfeld/perl/ch-2.pl b/challenge-227/laurent-rosenfeld/perl/ch-2.pl
new file mode 100644
index 0000000000..26470af669
--- /dev/null
+++ b/challenge-227/laurent-rosenfeld/perl/ch-2.pl
@@ -0,0 +1,63 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use feature qw/say/;
+
+my %rom_tab = (I => 1, V => 5, X => 10, L => 50,
+ C => 100, D => 500, M => 1000,
+ IV => 4, IX => 9, XL => 40, XC => 90,
+ CD => 400, CM => 900);
+
+sub from_roman {
+ my $roman = uc shift;
+ my $arabic = 0;
+ my $prev_letter = "M";
+ for my $letter (split //, $roman) {
+ $arabic -= 2 * $rom_tab{$prev_letter}
+ if $rom_tab{$letter} > $rom_tab{$prev_letter};
+ $arabic += $rom_tab{$letter};
+ $prev_letter = $letter;
+ }
+ return $arabic;
+}
+
+sub to_roman {
+ my $arabic = shift;
+ warn "$arabic out of bounds"
+ unless $arabic > 0 and $arabic < 4000;
+ my $roman = "";
+ for my $key (sort { $rom_tab{$b} <=> $rom_tab{$a} }
+ keys %rom_tab) {
+ my $num = int ($arabic / $rom_tab{$key});
+ $roman .= $key x $num;
+ $arabic -= $rom_tab{$key} * $num;
+ }
+ return $roman;
+}
+sub process_input {
+ my ($rom1, $op, $rom2) = split /\s+/, $_[0];
+ my $arabic1 = from_roman $rom1;
+ my $arabic2 = from_roman $rom2;
+ my $result = $op eq '+' ? $arabic1 + $arabic2 :
+ $op eq '-' ? $arabic1 - $arabic2 :
+ $op eq '/' ? $arabic1 / $arabic2 :
+ $op eq '*' ? $arabic1 * $arabic2 :
+ $op eq '**' ? $arabic1 ** $arabic2:
+ "illegal";
+ return "nulla (they didn't have a symbol for 0)"
+ if $result == 0;
+ return "non potest (they didn't do fractions)"
+ if int($result) != $result;
+ return "non potest (they only went up to 3999)"
+ if $result >= 4000;
+ return "non potest (no negative numbers)"
+ if $result < 0;
+ return to_roman $result;
+}
+
+for my $test ("IV + V", "M - I", "X / II", "XI * VI",
+ "VII ** III", "V - V", "V / II", "MMM + M",
+ "V - X ", "X - V") {
+ printf "%-10s => ", $test;
+ say process_input $test;
+}
diff --git a/challenge-227/laurent-rosenfeld/raku/ch-2.raku b/challenge-227/laurent-rosenfeld/raku/ch-2.raku
new file mode 100644
index 0000000000..94456d0776
--- /dev/null
+++ b/challenge-227/laurent-rosenfeld/raku/ch-2.raku
@@ -0,0 +1,57 @@
+subset Roman-str of Str where $_ ~~ /^<[IVXLCDMivxlcdm]>+$/;
+
+my %rom-tab = < I 1 V 5 X 10 L 50 C 100 D 500 M 1000
+ IV 4 IX 9 XL 40 XC 90 CD 400 CM 900 >;
+my @ordered_romans = reverse sort { %rom-tab{$_} }, keys %rom-tab;
+
+sub from-roman (Roman-str $roman) {
+ my $numeric = 0;
+ my $prev_letter = "M";
+ for $roman.uc.comb -> $letter {
+ $numeric -= 2 * %rom-tab{$prev_letter}
+ if %rom-tab{$letter} > %rom-tab{$prev_letter};
+ $numeric += %rom-tab{$letter};
+ # say "$letter $numeric";
+ $prev_letter = $letter;
+ }
+ return $numeric;
+}
+
+sub to-roman (Int $arabic is copy where { 0 < $_ < 4000 }) {
+ my $roman = "";
+ for @ordered_romans -> $key {
+ my $num = ($arabic / %rom-tab{$key}).Int;
+ $roman ~= $key x $num;
+ $arabic -= %rom-tab{$key} * $num;
+ }
+ return $roman;
+}
+sub process-input (Str $in) {
+ my ($rom1, $op, $rom2) = split /\s+/, $in;
+ my $arabic1 = from-roman $rom1;
+ my $arabic2 = from-roman $rom2;
+ my $result;
+ given $op {
+ when '+' { $result = $arabic1 + $arabic2 }
+ when '-' { $result = $arabic1 - $arabic2 }
+ when '*' { $result = $arabic1 * $arabic2 }
+ when '/' { $result = $arabic1 / $arabic2 }
+ when '**' { $result = $arabic1 ** $arabic2 }
+ }
+ return "nulla (they didn't have a symbol for 0)"
+ if $result == 0;
+ return "non potest (they didn't do fractions)"
+ if $result.round != $result;
+ return "non potest (they only went up to 3999)"
+ if $result >= 4000;
+ return "non potest (no negative numbers)"
+ if $result < 0;
+ return to-roman $result.round;
+}
+
+for "IV + V", "M - I", "X / II", "XI * VI",
+ "VII ** III", "V - V", "V / II", "MMM + M",
+ "V - X ", "X - V" -> $test-expr {
+ printf "%-10s => ", $test-expr;
+ say process-input $test-expr;
+}