Project Euler #89: Roman numerals

Sort by

recency

|

12 Discussions

|

  • + 0 comments

    Python 3

    NUMBERS_MAP = dict(IV=4, IX=9, XL=40, XC=90, CD=400, CM=900, I=1, V=5, X=10, L=50, C=100, D=500, M=1000).items()
    
    def to_roman(num: int) -> str:
        roman = ''
        for v, k in sorted(NUMBERS_MAP, key=lambda x: -x[1]):
            roman += num // k * v
            num -= num // k * k
        return roman
    
    def to_arabian(num: str) -> int:
        dec = 0
        for k, v in NUMBERS_MAP:
            oldlen, num = len(num), num.replace(k, '')
            dec += (oldlen - len(num)) * v // len(k)
        return dec
        
    [print(to_roman(to_arabian(input()))) for _ in range(int(input()))]
    
  • + 0 comments

    Ruby:

    class String
      ROMAN = {'I' => 1,
               'V' => 5,
               'X' => 10,
               'L' => 50,
               'C' => 100,
               'D' => 500,
               'M' => 1000 }
    
      def roman_to_i
        split('').collect {|s| 
          ROMAN[s] 
        }.inject([0, nil]) {|r, v|
          [r.first + v - ((!r.last.nil? && (r.last < v)) ? 2 * r.last : 0), v]
        }.first
      end  
    end
    
    class Integer
      
      class MagnitudeToRoman
        attr_reader :order
        
        def initialize(mag, chars)
        
          l1 = lambda {|r, ds|
            (r.last >= ds.first) ? [r.first + ds.last, r.last - ds.first] : r
          }
    
          l2 = lambda {|r, ds|
            [r.first + ds.last * (r.last / ds.first), r.last % ds.first]
          }
          chars = chars.split('')
          @order = [[9 * mag, chars.last + chars.first, l1],
                    [5 * mag, chars[1],                 l1],
                    [4 * mag, chars.last + chars[1],    l1],
                    [    mag, chars.last,               l2]
          ]
        end
        
        def call(r)
          order.inject(r) {|r1, o|
            o.last.call(r1, o[0...-1])
          }
        end
      end
      
      MAG_ORDER = [ MagnitudeToRoman.new(100, "MDC"),
                    MagnitudeToRoman.new(10,  "CLX"),
                    MagnitudeToRoman.new(1,   "XVI"),
                  ]
      
      def to_roman
        MAG_ORDER.inject(['M' * (self/1000), self % 1000]) {|r, mtr|
          mtr.call(r)
        }.first
      end
    end
    
    n = readline.to_i
    
    n.times {
      puts readline.strip.roman_to_i.to_roman
    }
    
  • + 0 comments

    I did this worked,it pretty well:

    def rtod_converter(roman):
        roman_arr = [c for c in roman]
        for i,el in enumerate(roman_arr):
            if el == 'I':
                roman_arr[i]=1
            elif el == 'V':
                roman_arr[i]=5
            elif el == 'X':
                roman_arr[i]=10
            elif el == 'L':
                roman_arr[i]=50
            elif el == 'C':
                roman_arr[i]=100
            elif el == 'D':
                roman_arr[i]=500
            elif el == 'M':
                roman_arr[i]=1000
            else :
                roman_arr[i]=0
        anchor = max(roman_arr)
        flip = -1
        value = 0
        for i,el in enumerate(roman_arr):
            if el == anchor:
                flip = 1
            value += (flip) * el
        return value
    
    def dtor_converter(num):
        num_arr = [i for i in str(num)]
        num_arr = num_arr[::-1]
        roman_arr = []
        m_arr = num_arr[3:]
        m_count = ''.join(m_arr[::-1])
        m_app = ''
        if m_count:
            m_count = int(m_count)
            m_app = 'M'*m_count
        for i,el in enumerate(num_arr):
            unit = ''
            penta= ''
            deca = ''
            if i == 0:
                unit = 'I'
                penta = 'V'
                deca = 'X'
            elif i == 1:
                unit = 'X'
                penta = 'L'
                deca = 'C'
            elif i == 2:
                unit = 'C'
                penta = 'D'
                deca = 'M'
            if el == '1':
                roman_arr.append(unit)
            elif el == '2':
                roman_arr.append(unit*2)
            elif el == '3':
                roman_arr.append(unit*3)
            elif el == '4':
                roman_arr.append(penta+unit)
            elif el == '5':
                roman_arr.append(penta)
            elif el == '6':
                roman_arr.append(unit+penta)
            elif el == '7':
                roman_arr.append((unit*2)+penta)
            elif el == '8':
                roman_arr.append((unit*3)+penta)
            elif el == '9':
                roman_arr.append(deca+unit)
        roman_arr.append(m_app)
        roman = ''.join(roman_arr)
        return(roman[::-1])
    
    times = int(input())
    while times:
        s=str(input())
        value = rtod_converter(s)
        result = dtor_converter(value)
        print(result)
        times -= 1
    
  • + 0 comments

    To make your life easier:

    string Cs[] = { "","C","CC","CCC", "CD", "D", "DC", "DCC", "DCCC", "CM" }; string Xs[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; string Is[] = { "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX" };

  • + 0 comments

    This Hacker Rank question looks similar to the original Project Euler question, but it's actually quite different.

    For the start, Project Euler only requires you "count" the character differences, while Hacker Rank requires you to actually convert to the short form. More problematic difference is that their inputs follow different rules. All of Project Euler inputs are still "valid": e.g. only one 'V' can appear in a string.

    I ended up having two different solutions for these questions. I had a solution passing all tests in Hacker Rank, but failing Project Euler.