Skip to content

Instantly share code, notes, and snippets.

@david-meza
Last active November 9, 2023 10:01
Show Gist options
  • Save david-meza/67124a0ff783f386a01d to your computer and use it in GitHub Desktop.
Save david-meza/67124a0ff783f386a01d to your computer and use it in GitHub Desktop.
Convert arabic to roman numerals in Ruby
class Fixnum
# Constant variable with 'unique' roman numerals, plus some special cases (e.g. "IV, IX, XC, CM...")
ROMANS = { 1000 => "M",
900 => "CM",
500 => "D",
400 => "CD",
100 => "C",
90 => "XC",
50 => "L",
40 => "XL",
10 => "X",
9 => "IX",
5 => "V",
4 => "IV",
1 => "I" }
def to_roman
# If the number's already on the hash return the value, otherwise decompose it into numbers that are in it.
ROMANS[self] || break_composite_roman(self)
end
private
def break_composite_roman(num)
# We start with an empty string and divide by the largest roman numeral possible in the hash
# Then we keep breaking down the remainder until it is 0
ROMANS.reduce("") do | memo, (arabic, roman) |
quotient, num = num.divmod(arabic)
# We multiply the quotient by the key's value (e.g. "I" * 3 = "III") and push it to the end of the string
memo << roman * quotient
end
end
end
#!/usr/bin/env ruby
gem 'minitest', '>= 5.0.0'
require 'minitest/autorun'
require_relative 'roman_numerals'
class RomanNumeralsTest < Minitest::Test
def test_1
assert_equal 'I', 1.to_roman
end
def test_2
assert_equal 'II', 2.to_roman
end
def test_3
assert_equal 'III', 3.to_roman
end
def test_4
assert_equal 'IV', 4.to_roman
end
def test_5
assert_equal 'V', 5.to_roman
end
def test_6
assert_equal 'VI', 6.to_roman
end
def test_9
assert_equal 'IX', 9.to_roman
end
def test_27
assert_equal 'XXVII', 27.to_roman
end
def test_48
assert_equal 'XLVIII', 48.to_roman
end
def test_59
assert_equal 'LIX', 59.to_roman
end
def test_93
assert_equal 'XCIII', 93.to_roman
end
def test_141
assert_equal 'CXLI', 141.to_roman
end
def test_163
assert_equal 'CLXIII', 163.to_roman
end
def test_402
assert_equal 'CDII', 402.to_roman
end
def test_575
assert_equal 'DLXXV', 575.to_roman
end
def test_911
assert_equal 'CMXI', 911.to_roman
end
def test_1024
assert_equal 'MXXIV', 1024.to_roman
end
def test_3000
assert_equal 'MMM', 3000.to_roman
end
def test_99
assert_equal 'XCIX', 99.to_roman
end
def test_2015
assert_equal 'MMXV', 2015.to_roman
end
def test_3999
assert_equal 'MMMCMXCIX', 3999.to_roman
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment