Skip to content

Instantly share code, notes, and snippets.

@neumachen
Forked from mecampbellsoup/roman_numerals.rb
Created March 12, 2020 21:48
Show Gist options
  • Select an option

  • Save neumachen/561a4f513f0c5b922c5a673562e8ad00 to your computer and use it in GitHub Desktop.

Select an option

Save neumachen/561a4f513f0c5b922c5a673562e8ad00 to your computer and use it in GitHub Desktop.
Awesome roman numeral algorithm in Ruby :)
require 'pry'
# ```
# 1 => I
# 10 => X
# 7 => VII
# ```
# There is no need to be able to convert numbers larger than about 3000. (The Romans themselves didn't tend to go any higher)
# Wikipedia says: Modern Roman numerals ... are written by expressing each digit separately starting with the left most digit and skipping any digit with a value of zero.
# To see this in practice, consider the example of 1990.
# In Roman numerals 1990 is MCMXC:
# 1000=M
# 900=CM
# 90=XC
# 2008 is written as MMVIII:
# 2000=MM
# 8=VIII
# See also: http://www.novaroma.org/via_romana/numbers.html
class Integer
@@values = {
1=>"I",
4=>"IV",
5=>"V",
9=>"IX",
10=>"X",
40=>"XL",
50=>"L",
90=>"XC",
100=>"C",
400=>"CD",
500=>"D",
900=>"CM",
1000=>"M"
}
def to_roman_descending #this one requires numeral-arabic pairs in descending order, i.e. 1000=>"M" on down
return 0 if self == 0
roman = ""
integer = self
@@values.each do |k,v|
until integer < k
roman << v
integer -= k
end
end
roman
end
def to_roman
integer = self
roman = ""
while integer > 0
if @@values[integer]
roman += @@values[integer]
return roman
end
roman += @@values[next_lower_key(integer)] # increment the roman numeral string here
integer -= next_lower_key(integer) # decrement the arabic integer here
end
end
def next_lower_key(integer)
arabics = @@values.keys
next_lower_index = (arabics.push(integer).sort.index(integer))-1
arabics[next_lower_index]
end
end
require_relative 'roman_numerals'
RSpec.configure do |config|
# Use color in STDOUT
config.color_enabled = true
# Use color not only in STDOUT but also in pagers and files
config.tty = true
# Use the specified formatter
config.formatter = :progress # :progress, :html, :textmate
end
describe Integer, '#to_roman' do
it 'converts 1' do
1.to_roman.should eq 'I'
end
it 'converts 2' do
2.to_roman.should eq 'II'
end
it 'converts 3' do
3.to_roman.should eq 'III'
end
it 'converts 4' do
4.to_roman.should eq 'IV'
end
it 'converts 5' do
5.to_roman.should eq 'V'
end
it 'converts 6' do
6.to_roman.should eq 'VI'
end
it 'converts 9' do
9.to_roman.should eq 'IX'
end
it 'converts 27' do
27.to_roman.should eq 'XXVII'
end
it 'converts 48' do
48.to_roman.should eq 'XLVIII'
end
it 'converts 59' do
59.to_roman.should eq 'LIX'
end
it 'converts 93' do
93.to_roman.should eq 'XCIII'
end
it 'converts 141' do
141.to_roman.should eq 'CXLI'
end
it 'converts 163' do
163.to_roman.should eq 'CLXIII'
end
it 'converts 402' do
402.to_roman.should eq 'CDII'
end
it 'converts 575' do
575.to_roman.should eq 'DLXXV'
end
it 'converts 911' do
911.to_roman.should eq 'CMXI'
end
it 'converts 1024' do
1024.to_roman.should eq 'MXXIV'
end
it 'converts 3000' do
3000.to_roman.should eq 'MMM'
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment