Arabic numbers to Roman numerals conversion The following converts Arabic numbers to Roman numerals.

I decided to factor each digit into its place value, then use a mapping to convert it to its Roman equivalent. 

For example, 1997 is factored to:

\$(1 \times 10^3) + (9 \times 10^2) + (9 \times 10^1) + (7 \times 10^0) = 1000 + 900 + 90 + 7\$

The Roman numerals for those numbers are then retrieved from the mapping.

class Integer
  def to_roman
    mappings = {
         1 =&gt; 'I',
         2 =&gt; 'II',
         3 =&gt; 'III',
         4 =&gt; 'IV',
         5 =&gt; 'V',
         6 =&gt; 'VI',
         7 =&gt; 'VII',
         8 =&gt; 'VIII',
         9 =&gt; 'IX',
        10 =&gt; 'X',
        20 =&gt; 'XX',
        30 =&gt; 'XXX',
        40 =&gt; 'XL',
        50 =&gt; 'L',
        60 =&gt; 'LX',
        70 =&gt; 'LXX',
        80 =&gt; 'LXXX',
        90 =&gt; 'XC',
       100 =&gt; 'C',
       200 =&gt; 'CC',
       300 =&gt; 'CCC',
       400 =&gt; 'CD',
       500 =&gt; 'D',
       600 =&gt; 'DC',
       700 =&gt; 'DCC',
       800 =&gt; 'DCCC',
       900 =&gt; 'CM',
      1000 =&gt; 'M',
      2000 =&gt; 'MM',
      3000 =&gt; 'MMM'
    }

    roman = []
    to_s.chars.reverse.each.with_index(0) do |digit, i|
      roman.unshift(mappings[digit.to_i * 10**i])
    end

    roman.join
  end
end


I like using exponents to factor each digit into its value place. I don't like having to define a mapping for each number from 1 to 3 and 6 to 8, and repeat that for the 10s, 100s, and 1000s digits.
Similar to dankohn's comment, there are really only a handful of operations going on, just with different character sets.

Here is my quick implementation.  It only handles the base 10 digits, and dynamically swaps out character sets depending on the power of the number.

def to_roman(digits)
    numeral_sets = {  1=&gt;['I', 'V', 'X'], 
                     10=&gt;['X', 'L', 'C'], 
                    100=&gt;['C', 'D', 'M'], 
                   1000=&gt;['M', "\u2181", "\u2182"] }

    str = ''
    digits.reverse.each.with_index do |d, ix|
        set = numeral_sets[10**ix]
        case d
            when 0 then roman = ''
            when 1..3 then roman = set[0] * d
            when 4 then roman = "%s%s" % [set[0], set[1]]
            when 5 then roman = set[1]
            when 6..8 then roman = "%s%s" % [set[1], set[0] * (d-5)]
            when 9 then roman = "%s%s" % [set[0], set[2]]
        end
        str = str.insert(0, roman)
    end
    str
end


And a few tests:

puts to_roman [1,9,9,7] # expected MCMXCVII
puts to_roman [1,9,0,7] # expected MCMVII
puts to_roman [5,6,7,8] # expected ↁDCLXXVIII