package Roman; my %val = ( 'M' => 1000, 'CM' => 900, 'D' => 500, 'CD' => 400, 'C' => 100, 'XC' => 90, 'L' => 50, 'XL' => 40, 'X' => 10, 'IX' => 9, 'V' => 5, 'IV' => 4, 'I' => 1, ); my %rom = reverse %val; my $rpat = join '|', sort {$val{$b} <=> $val{$a}} keys %val; my @vals = sort {$b <=> $a} values %val; sub import { my $pack = shift; my $caller = caller; my %args = @_; my $top = $args{Top} || 3999; my $i; for ($i=1; $i<= $top; $i++) { my $name = $caller . '::' . i2r($i); my $var; tie $var, $pack, $i; *{$name} = \$var; } } sub new { &TIESCALAR; } sub TIESCALAR { my $pack = shift; my $v = shift; bless \$v => $pack; } sub FETCH { my $self = shift; $$self; } sub r2i { my $r = shift; my $i = 0; while ($r =~ /\G($rpat)/og) { $i += $val{$1}; } $i; } sub i2r { use Carp; my $i = shift; my $r = ''; foreach $v (@vals) { while ($v <= $i) { $i -= $v; $r .= $rom{$v}; return $r if $i ==0; } } croak "Can't convert number $i to Roman numeral"; } sub stringize { my $self = shift; my $i = $$self; i2r($i); } sub STORE { use Carp; my $self = shift; my $val = $$self; my $rom = i2r($val); carp "Warning; Tried to modify the value of Roman numeral $rom"; my $new = shift; $new; }