Skip to content

Instantly share code, notes, and snippets.

@fallengiants
Last active July 15, 2018 04:13
Show Gist options
  • Select an option

  • Save fallengiants/9989686dcf41f41de816334b628f7797 to your computer and use it in GitHub Desktop.

Select an option

Save fallengiants/9989686dcf41f41de816334b628f7797 to your computer and use it in GitHub Desktop.
class Integer # so that 3.to_roman() will return a result
Roman = 'IVXLCDM' # cardinally ordered roman numerals
def to_roman
raise "Number too large" if self > 4999 # string does not contain characters for > 4999
n, nsize = self, Math.log10(self).to_i # n = this number, nsize = number of digits in this number
nsize.downto(0).map do |pow| # pow = each digit from the left (i.e. 4,3,2,1 for 1000) - 1 (zero is the first index)
mid = pow << 1 # mid = pow * 2 (so that for every multiple of 10, there are two roman characters)
current = n / (10 ** pow) # current = T where Txxx is the current number and pow is digits from right; i.e. 1234 and pow is 3 -> T == 1
n = n % (10 ** pow) # n = the leftovers; i.e. if 1234 and pow is 3, then n == 234
mods = current % 5 # mods = remainder of current divided by 5; therefore, offset from a pure single-character roman digit
out = '' # create a new string for output
out << Roman[mid] if mods == 4 # if mods is 4, we have a pre-pointer digit (i.e. IV, IX, XL, ...); add that here
out << Roman[mid + (current == 9 ? 2 : 1)] if current > 3 # add the main roman numeral; i.e. if n == 55 and pow == 1 (dealing with the 50), mid == 2 (zero index), current == 5, Roman[mid+1] == 'L'
out << (Roman[mid] * mods) if mods < 4 # numbers after main roman digit; if % 5 is less than 4 (i.e. does not have a prefix digit), add Roman[mid] digits for each remaining digit (i.e. 3 returns III here)
out # function return value (string)
end.join # concatenate strings
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment