From 1823dc2593cc5ada13c3d9e8f941b1170ddcda29 Mon Sep 17 00:00:00 2001 From: Branden Colen Date: Mon, 5 Apr 2021 21:48:17 -0500 Subject: [PATCH] cleaned up code --- romannumeral.go | 77 +++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 41 deletions(-) diff --git a/romannumeral.go b/romannumeral.go index cca5a6d..ac29dec 100644 --- a/romannumeral.go +++ b/romannumeral.go @@ -10,46 +10,41 @@ import ( "errors" ) -const ( - _maxRoman = 3999 - _minRoman = 1 -) - -var ( - InvalidRomanNumeral = errors.New("invalid roman numeral") - IntegerOutOfBounds = errors.New("integer must be between 1 and 3999") -) - // numeral describes the value and symbol of a single roman numeral type numeral struct { val int sym []byte } -// _numerals are all unique numerals ordered from largest to smallest -var _numerals = []numeral{ - {1000, []byte("M")}, - {900, []byte("CM")}, - {500, []byte("D")}, - {400, []byte("CD")}, - {100, []byte("C")}, - {90, []byte("XC")}, - {50, []byte("L")}, - {40, []byte("XL")}, - {10, []byte("X")}, - {9, []byte("IX")}, - {5, []byte("V")}, - {4, []byte("IV")}, - {1, []byte("I")}, -} - -// lookup arrays used for converting from an int to a roman numeral extremely quickly. -// method from here: https://rosettacode.org/wiki/Roman_numerals/Encode#Go var ( - m0 = []string{"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"} - m1 = []string{"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"} - m2 = []string{"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"} - m3 = []string{"", "M", "MM", "MMM"} + // InvalidRomanNumeral - error for when a roman numeral string provided is not a valid roman numeral + InvalidRomanNumeral = errors.New("invalid roman numeral") + // IntegerOutOfBounds - error for when the integer provided is invalid and unable to be converted to a roman numeral + IntegerOutOfBounds = errors.New("integer must be between 1 and 3999") + + // all unique numerals ordered from largest to smallest + nums = []numeral{ + {1000, []byte("M")}, + {900, []byte("CM")}, + {500, []byte("D")}, + {400, []byte("CD")}, + {100, []byte("C")}, + {90, []byte("XC")}, + {50, []byte("L")}, + {40, []byte("XL")}, + {10, []byte("X")}, + {9, []byte("IX")}, + {5, []byte("V")}, + {4, []byte("IV")}, + {1, []byte("I")}, + } + + // lookup arrays used for converting from an int to a roman numeral extremely quickly. + // method from here: https://rosettacode.org/wiki/Roman_numerals/Encode#Go + r0 = []string{"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"} + r1 = []string{"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"} + r2 = []string{"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"} + r3 = []string{"", "M", "MM", "MMM"} ) // IntToString converts an integer value to a roman numeral string. An error is @@ -71,13 +66,13 @@ func IntToBytes(input int) ([]byte, error) { // outOfBounds checks to ensure an input value is valid for roman numerals without the need of // vinculum (used for values of 4,000 and greater) func outOfBounds(input int) bool { - return input < _minRoman || input > _maxRoman + return input < 1 || input > 3999 } func intToRoman(n int) string { // This is efficient in Go. The 4 operands are evaluated, // then a single allocation is made of the exact size needed for the result. - return m3[n%1e4/1e3] + m2[n%1e3/1e2] + m1[n%100/10] + m0[n%10] + return r3[n%1e4/1e3] + r2[n%1e3/1e2] + r1[n%100/10] + r0[n%10] } // StringToInt converts a roman numeral string to an integer. Roman numerals for numbers @@ -102,13 +97,13 @@ func BytesToInt(input []byte) (int, error) { func romanToInt(input []byte) (int, bool) { var output int - for _, rom := range _numerals { - for bytes.HasPrefix(input, rom.sym) { - output += rom.val - input = input[len(rom.sym):] + for _, n := range nums { + for bytes.HasPrefix(input, n.sym) { + output += n.val + input = input[len(n.sym):] } } - // If we are still left with input string values then the - // input was invalid and the bool is returned as False + // if we are still left with input string values then the + // input was invalid and the bool is returned as false return output, len(input) == 0 }