Roman Numerals Decoder in Golang

1 min read 393 words

The challenge

Create a function that takes a Roman numeral as its argument and returns its value as a numeric decimal integer. You don’t need to validate the form of the Roman numeral.

Modern Roman numerals are written by expressing each decimal digit of the number to be encoded separately, starting with the leftmost digit and skipping any 0s. So 1990 is rendered “MCMXC” (1000 = M, 900 = CM, 90 = XC) and 2008 is rendered “MMVIII” (2000 = MM, 8 = VIII). The Roman numeral for 1666, “MDCLXVI”, uses each letter in descending order.

Example:

// should return 21
solution('XXI');

Help:

Symbol    Value
I          1
V          5
X          10
L          50
C          100
D          500
M          1,000

The solution in Golang

Option 1:

package solution
var decoder = map[rune]int {
    'I': 1,
    'V': 5,
    'X': 10,
    'L': 50,
    'C': 100,
    'D': 500,
    'M': 1000,
}
func Decode(roman string) int {
    if len(roman) == 0 { return 0 }
    first := decoder[rune(roman[0])]
    if len(roman) == 1 { return first }
    next := decoder[rune(roman[1])]
    if next > first { return (next - first) + Decode(roman[2:]) }
    return first + Decode(roman[1:])
}

Option 2:

package solution
func Decode(roman string) int {
  var sum int
  var Roman = map[byte] int {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000,}
  for k, v := range roman {
    if k < len(roman) - 1 && Roman[byte(roman[k + 1])] > Roman[byte(roman[k])] {
      sum -= Roman[byte(v)]
    } else {
      sum += Roman[byte(v)]
    }
  }
  return sum
}

Option 3:

package solution
func Decode(roman string) int {
  translateRoman := map[byte]int{'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
  var decNum, tmpNum int
  for i := len(roman) - 1; i >= 0; i-- {
    romanDigit := roman[i]
    decDigit := translateRoman[romanDigit]
    if decDigit < tmpNum {
      decNum -= decDigit
    } else {
      decNum += decDigit
      tmpNum = decDigit
    }
  }
  return decNum
}

Test cases to validate our solution

package solution_test
import (
  . "github.com/onsi/ginkgo"
  . "github.com/onsi/gomega"
)
var _ = Describe("test roman to decimal converter", func() {
   It("should give decimal number from roman", func() {
     Expect(Decode("XXI")).To(Equal(21))
   })
   It("should give decimal number from roman", func() {
     Expect(Decode("I")).To(Equal(1))
   })
   It("should give decimal number from roman", func() {
     Expect(Decode("IV")).To(Equal(4))
   })
   It("should give decimal number from roman", func() {
     Expect(Decode("MMVIII")).To(Equal(2008))
   })
   It("should give decimal number from roman", func() {
     Expect(Decode("MDCLXVI")).To(Equal(1666))
   })
})
Tags:
Andrew
Andrew

Andrew is a visionary software engineer and DevOps expert with a proven track record of delivering cutting-edge solutions that drive innovation at Ataiva.com. As a leader on numerous high-profile projects, Andrew brings his exceptional technical expertise and collaborative leadership skills to the table, fostering a culture of agility and excellence within the team. With a passion for architecting scalable systems, automating workflows, and empowering teams, Andrew is a sought-after authority in the field of software development and DevOps.

Tags

Recent Posts