diff options
Diffstat (limited to '010/ch1.pl')
-rwxr-xr-x | 010/ch1.pl | 174 |
1 files changed, 87 insertions, 87 deletions
@@ -11,108 +11,108 @@ use warnings; # CLI usage sub usage { - print "$0 {-e ARABIC | -d ROMAN | --test}\n"; - exit shift; + print "$0 {-e ARABIC | -d ROMAN | --test}\n"; + exit shift; } usage -1 unless @ARGV > 0; if ($ARGV[0] eq "--test") { - test(); + test(); } else { - usage -1 unless @ARGV == 2; - if ($ARGV[0] eq "-d") { - print decode($ARGV[1]), "\n"; - } elsif ($ARGV[0] eq "-e") { - print encode($ARGV[1]), "\n"; - } else { - usage -1; - } + usage -1 unless @ARGV == 2; + if ($ARGV[0] eq "-d") { + print decode($ARGV[1]), "\n"; + } elsif ($ARGV[0] eq "-e") { + print encode($ARGV[1]), "\n"; + } else { + usage -1; + } } # roman -> arabic sub decode { - my @roman = split //, shift; - - # Decimal value of each roman symbol - my %dec = ( - M => 1000, - D => 500, - C => 100, - L => 50, - X => 10, - V => 5, - I => 1, - ); - my $arabic = 0; # Return value - - # Iterate over roman symbols - for (my $i = 0; $i < @roman; $i++) { - # Get current and next symbols - my ($currsym, $nextsym) = @roman[$i .. $i+1]; - my $val = $dec{$currsym}; - - # Sub current value if next symbol is bigger; add it otherwise - if (defined $nextsym && $val < $dec{$nextsym}) { - $arabic -= $val; - } else { - $arabic += $val; - } - } - - return $arabic; + my @roman = split //, shift; + + # Decimal value of each roman symbol + my %dec = ( + M => 1000, + D => 500, + C => 100, + L => 50, + X => 10, + V => 5, + I => 1, + ); + my $arabic = 0; # Return value + + # Iterate over roman symbols + for (my $i = 0; $i < @roman; $i++) { + # Get current and next symbols + my ($currsym, $nextsym) = @roman[$i .. $i+1]; + my $val = $dec{$currsym}; + + # Sub current value if next symbol is bigger; add it otherwise + if (defined $nextsym && $val < $dec{$nextsym}) { + $arabic -= $val; + } else { + $arabic += $val; + } + } + + return $arabic; } # arabic -> roman sub encode { - die "ERROR: Unable to encode numbers bigger than 9999" if $_[0] > 9999; - - my @arabic = split //, shift; - - my @symbols = ("I", "V", "X", "L", "C", "D", "M"); - my @roman; # Return value (roman symbols) - - # Iterate arabic digits from right to left (upward units) - for (my $i = $#arabic; $i >= 0; $i--) { - my $digit = $arabic[$i]; - - # Roman symbols corresponding to (1-5-10) given the current base - my ($one, $five, $ten) = @symbols; - - # Roman symbols to add at the beginning of the current result - my @to_add; - - # 4 and 9 are (5-1) and (10-1) respectively - if ($one ne "M" && ($digit == 4 || $digit == 9)) { - push @to_add, $one; - $digit++; - } - - # Add the roman equivalents to the current digit - if ($one eq "M") { - # For 4000-9999, just add as much M's as needed - push @to_add, (map $one, (1..$digit)); - } elsif ($digit == 10) { - push @to_add, $ten; - } elsif ($digit > 4) { - push @to_add, ($five, map $one, (6..$digit)); - } elsif ($digit > 0) { - push @to_add, (map $one, (1..$digit)); - } - unshift @roman, @to_add; - - # For the next decimal, discard two roman symbols (one + five) - shift @symbols foreach (1..2); - } - - return join "", @roman; + die "ERROR: Unable to encode numbers bigger than 9999" if $_[0] > 9999; + + my @arabic = split //, shift; + + my @symbols = ("I", "V", "X", "L", "C", "D", "M"); + my @roman; # Return value (roman symbols) + + # Iterate arabic digits from right to left (upward units) + for (my $i = $#arabic; $i >= 0; $i--) { + my $digit = $arabic[$i]; + + # Roman symbols corresponding to (1-5-10) given the current base + my ($one, $five, $ten) = @symbols; + + # Roman symbols to add at the beginning of the current result + my @to_add; + + # 4 and 9 are (5-1) and (10-1) respectively + if ($one ne "M" && ($digit == 4 || $digit == 9)) { + push @to_add, $one; + $digit++; + } + + # Add the roman equivalents to the current digit + if ($one eq "M") { + # For 4000-9999, just add as much M's as needed + push @to_add, (map $one, (1..$digit)); + } elsif ($digit == 10) { + push @to_add, $ten; + } elsif ($digit > 4) { + push @to_add, ($five, map $one, (6..$digit)); + } elsif ($digit > 0) { + push @to_add, (map $one, (1..$digit)); + } + unshift @roman, @to_add; + + # For the next decimal, discard two roman symbols (one + five) + shift @symbols foreach (1..2); + } + + return join "", @roman; } # Property: # forall (x : Arabic). x == decode(encode(x)) sub test { - foreach my $i (1..9999) { - my $roman = encode($i); - my $arabic = decode($roman); - die "ERROR: $i -> $roman -> $arabic" if $i != $arabic; - } - print "Test successful\n"; + foreach my $i (1..9999) { + my $roman = encode($i); + my $arabic = decode($roman); + die "ERROR: $i -> $roman -> $arabic" if $i != $arabic; + } + print "Test successful\n"; } |