Roman numeral conversion

First time poster here...

I realize that rubyquiz.com is no longer really active, but some of the
code there is still used by people googling for example code (roman
numeral conversion in my case for a class I am taking), and I wanted to
point out that many of the solutions listed for quiz #22 are evaluating
roman to arabic numerals incorrectly.

If you run many of the solutions, especially the ones that use this
table:

        [ 1000, 'M' ],
        [ 900, 'CM' ],
        [ 500, 'D' ],
        [ 400, 'CD' ],
        [ 100, 'C' ],
        [ 90, 'XC' ],
        [ 50, 'L' ],
        [ 40, 'XL' ],
        [ 10, 'X' ],
        [ 9, 'IX' ],
        [ 5, 'V' ],
        [ 4, 'IV' ],
        [ 1, 'I' ]
        ]

...and then you try to evaluate the string value XD (for example), it
will convert this string to 510. This should not happen; XD is not a
legal roman numeral, DX would be 510, and CDXC would be 490. The
problem seems to be that in roman to arabic numeral conversion, the
solutions just add the raw values together. This means that converters
using this kind of conversion will accept any combination of roman
numeral values from the table above...regardless of order.

A crazier example:

If you evaluate XIV, you get 14, by finding X and then IV in the table
above and then adding their corresponding values together.

If you put in IXIVI, it will *also* evaluate to 14 by adding IX + IV + I
and accept it as a valid roman numeral.

I don't have a solution yet, but I thought I would at least point this
out in case someone is adding a to_roman method to Integer or something
and wants it to be 100% robust.

···

--
Posted via http://www.ruby-forum.com/.

how about that one (it's a little longish):

    class String
        def to_roman
            str = self.downcase
            raise SyntaxError, "Not a roman numeral" unless str =~
/^[mdclxvi]+$/
            raise SyntaxError, "Not a roman numeral" if
                %w{iiii vv xxxx ll cccc dd}.any? { |x| str.include?(x) }
            str.tr!("ivxlcdm", "0123456") # translate into numbers
            level, last, deviated, ret = 7, 0, false, 0
            table = [1,5,10,50,100,500,1000] # the translation table
            str.each_char do |char|
                num = char.to_i
                if num > level # means a deviation
                    raise SyntaxError, "Not a roman numeral" if deviated or
not # no double deviation
                        %w{01 02 23 24 45 46}.include?("#{last}#{num}") #
only allowed deviations
                    ret -= table[last]*2 # remedy deviation
                    level = last-1 # don't allow IXI or IXV etc.
                    deviated = true
                else
                    deviated = false
                    level = num # don't allow MLM etc.
                end
                ret += table[num]
                last = num
            end
            ret
        end
    end

fulfills all your examples, but i dunno if it's correct. would be great if
someone
could test this (let alone improve it).

What it checks for:
* only [ivxlcdm] allowed
* ixc may each only occur max. 3 times in a row
* vld may each only occur max once in a row
* when dropping to a certain level, only the following sequences may rise
    above that level: cm cd xc xl ix iv
* and not twice in a row, so ixc is not legal
* and after that, the level drops to the smaller char, so ixivi is not
legal

...and then you try to evaluate the string value XD (for example), it

···

will convert this string to 510. This should not happen; XD is not a
legal roman numeral, DX would be 510, and CDXC would be 490. The
problem seems to be that in roman to arabic numeral conversion, the
solutions just add the raw values together. This means that converters
using this kind of conversion will accept any combination of roman
numeral values from the table above...regardless of order.

A crazier example:

If you evaluate XIV, you get 14, by finding X and then IV in the table
above and then adding their corresponding values together.

If you put in IXIVI, it will *also* evaluate to 14 by adding IX + IV + I
and accept it as a valid roman numeral.

english/roman.rb checks out.

T.

···

On Sep 18, 1:26 pm, Brian Tickler <btick...@yahoo.com> wrote:

First time poster here...

I realize that rubyquiz.com is no longer really active, but some of the
code there is still used by people googling for example code (roman
numeral conversion in my case for a class I am taking), and I wanted to
point out that many of the solutions listed for quiz #22 are evaluating
roman to arabic numerals incorrectly.

If you run many of the solutions, especially the ones that use this
table:

    \[ 1000, &#39;M&#39;  \],
    \[  900, &#39;CM&#39; \],
    \[  500, &#39;D&#39;  \],
    \[  400, &#39;CD&#39; \],
    \[  100, &#39;C&#39;  \],
    \[   90, &#39;XC&#39; \],
    \[   50, &#39;L&#39;  \],
    \[   40, &#39;XL&#39; \],
    \[   10, &#39;X&#39;  \],
    \[    9, &#39;IX&#39; \],
    \[    5, &#39;V&#39;  \],
    \[    4, &#39;IV&#39; \],
    \[    1, &#39;I&#39;  \]
    \]

...and then you try to evaluate the string value XD (for example), it
will convert this string to 510. This should not happen; XD is not a
legal roman numeral, DX would be 510, and CDXC would be 490. The
problem seems to be that in roman to arabic numeral conversion, the
solutions just add the raw values together. This means that converters
using this kind of conversion will accept any combination of roman
numeral values from the table above...regardless of order.

A crazier example:

If you evaluate XIV, you get 14, by finding X and then IV in the table
above and then adding their corresponding values together.

If you put in IXIVI, it will *also* evaluate to 14 by adding IX + IV + I
and accept it as a valid roman numeral.

I don't have a solution yet, but I thought I would at least point this
out in case someone is adding a to_roman method to Integer or something
and wants it to be 100% robust.

Cool, I will give this a shot, but while I know enough about Roman
numerals, I am not an expert by any means, so I will leave any
"approvals" to someone that knows everything about them :).

···

--
Posted via http://www.ruby-forum.com/.