class RomanToArabic::Validator

Attributes

numerals[R]
roman_number[R]

Public Class Methods

new(roman_number) click to toggle source
# File lib/roman_to_arabic/validator.rb, line 3
def initialize(roman_number)
  @roman_number = roman_number.upcase
  @numerals = roman_number.chars.map(&:to_sym)
end

Public Instance Methods

valid?() click to toggle source
# File lib/roman_to_arabic/validator.rb, line 8
def valid?
  valid_characters? &&
    characters_are_not_repeated? &&
    valid_characters_order? &&
    valid_subtractions?
end

Private Instance Methods

characters_are_not_repeated?() click to toggle source

The symbols “I”, “X”, “C”, and “M” can be repeated three times in succession, but no more. “D”, “L”, and “V” can never be repeated.

# File lib/roman_to_arabic/validator.rb, line 26
def characters_are_not_repeated?
  (roman_number =~ /D{2,}|L{2,}|V{2,}|I{4,}|X{4,}|C{4,}|M{4,}/).nil?
end
valid_characters?() click to toggle source
# File lib/roman_to_arabic/validator.rb, line 19
def valid_characters?
  roman_number =~ /^[IVXLCDM]+$/
end
valid_characters_order?() click to toggle source

“I” can be subtracted from “V” and “X” only. /IL|IC|ID|IM/ “X” can be subtracted from “L” and “C” only. /XD|XM/ “C” can be subtracted from “D” and “M” only. “V”, “L”, and “D” can never be subtracted. /VX|VL|VC|VD|VM|LC|LD|LM|DM/

# File lib/roman_to_arabic/validator.rb, line 37
def valid_characters_order?
  (roman_number =~ /IL|IC|ID|IM|XD|XM|VX|VL|VC|VD|VM|LC|LD|LM|DM/).nil?
end
valid_subtractions?() click to toggle source

Only one small-value symbol may be subtracted from any large-value symbol. i.e. IIV considered invalid III, XXX, etc.. cases are covered by `#characters_are_not_repeated?`

# File lib/roman_to_arabic/validator.rb, line 44
def valid_subtractions?
  return true if roman_number.length < 3 # we are not interested if length is 2 or less

  for i in (1...(numerals.length - 1))
    current_number = DICTIONARY[numerals[i]]
    previous_number = DICTIONARY[numerals[i-1]]
    next_number = DICTIONARY[numerals[i+1]]

    if previous_number <= current_number && current_number < next_number
      return false
    end
  end

  true
end