LC 13. Roman to Integer

Published on
Reading time
2 min read

The problem

First Solution

In this quick and dirty first attempt, I just wrote out all the cases. It's a little long but gets the job done:

function romanToInt(s: string): number {
  let answer: number = 0
  for (let i = 0; i < s.length; i++) {
    if (s[i] === 'I') {
      if (s[i + 1] === 'V') {
        answer += 4
        i++
      } else if (s[i + 1] === 'X') {
        answer += 9
        i++
      } else {
        answer++
      }
    } else if (s[i] === 'V') {
      answer += 5
    } else if (s[i] === 'X') {
      if (s[i + 1] === 'L') {
        answer += 40
        i++
      } else if (s[i + 1] === 'C') {
        answer += 90
        i++
      } else {
        answer += 10
      }
    } else if (s[i] === 'L') {
      answer += 50
    } else if (s[i] === 'C') {
      if (s[i + 1] === 'D') {
        answer += 400
        i++
      } else if (s[i + 1] === 'M') {
        answer += 900
        i++
      } else {
        answer += 100
      }
    } else if (s[i] === 'D') {
      answer += 500
    } else if (s[i] === 'M') {
      answer += 1000
    }
  }

  return answer
}

More concise solution

I find this solution less readable as it has a trick to it. Here, all numbers are added, but 2 * previous is subtracted when an edge case is identified. For example, 'IV' would add 1 first, then add 5 - 1 - 1 to give 4. Again, 1 is subtracted first to give the value 4 and subtracted a second time to offset the previous iterations increment:

function romanToInt(s: string): number {
  const valueMap = {
    I: 1,
    V: 5,
    X: 10,
    L: 50,
    C: 100,
    D: 500,
    M: 1000,
  }
  let answer: number = 0
  for (let i = 0; i < s.length; i++) {
    if (valueMap[s[i]] > valueMap[s[i - 1]]) {
      // Subtract double the previous value since it was added
      // incorrectly in the previous iteration
      answer += valueMap[s[i]] - 2 * valueMap[s[i - 1]]
    } else {
      answer += valueMap[s[i]]
    }
  }

  return answer
}