Class: RomanNumbers::RomanNumber

Inherits:
Object
  • Object
show all
Defined in:
lib/roman_numbers/roman_number.rb

Constant Summary collapse

ROMAN_REPEATABLE_UNITS =
[
    {:unit => :M, :value => 1000}, # element first
    {:unit => :C, :value => 100},
    {:unit => :X, :value => 10},
    {:unit => :I, :value => 1} # element last
].sort { |x, y| y[:value] <=> x[:value] }
ROMAN_NON_REPEATABLE_UNITS_1 =
[
    {:unit => :D, :value => 500}, # element first
    {:unit => :L, :value => 50},
    {:unit => :V, :value => 5}, # element last
].sort { |x, y| y[:value] <=> x[:value] }
ROMAN_NON_REPEATABLE_UNITS_2 =
[
    {:unit => :CM, :value => 900}, # element first
    {:unit => :CD, :value => 400},
    {:unit => :XC, :value => 90},
    {:unit => :XL, :value => 40},
    {:unit => :IX, :value => 9},
    {:unit => :IV, :value => 4} # element last
].sort { |x, y| y[:value] <=> x[:value] }
ROMAN_NON_REPEATABLE_UNITS =
(ROMAN_NON_REPEATABLE_UNITS_1 + ROMAN_NON_REPEATABLE_UNITS_2).sort { |x, y| y[:value] <=> x[:value] }
ROMAN_DOUBLE_UNITS =
ROMAN_NON_REPEATABLE_UNITS_2.sort { |x, y| y[:value] <=> x[:value] }
ROMAN_SINGLE_UNITS =
(ROMAN_NON_REPEATABLE_UNITS_1 + ROMAN_REPEATABLE_UNITS).sort { |x, y| y[:value] <=> x[:value] }
ROMAN_UNITS =
(ROMAN_REPEATABLE_UNITS + ROMAN_NON_REPEATABLE_UNITS_1 + ROMAN_NON_REPEATABLE_UNITS_2).sort { |x, y| y[:value] <=> x[:value] }
MAX_ALLOWED_REPETITION =

based on above non_repeatable units, allowed repetition is 3

3

Instance Method Summary collapse

Constructor Details

#initialize(input) ⇒ RomanNumber

initializing element



37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/roman_numbers/roman_number.rb', line 37

def initialize(input)
  # checking input type and setting instance variables
  case input
    when Integer
      @input_integer = input
      @staged_roman_hash = Array.new
      @output_roman = String.new
    when String
      @input_string = input.upcase
      @output_arabic = 0
  end
end

Instance Method Details

#convert_decimal_to_roman(input_integer = @input_integer) ⇒ Object

converts arabic to roman



51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/roman_numbers/roman_number.rb', line 51

def convert_decimal_to_roman(input_integer=@input_integer)
  # validating input
  unless (1..3999).include? input_integer
    raise InvalidInputError, "Invalid Input: #{input_integer}"
  end
  # getting staged roman hash
  calculate_staged_roman_hash(input_integer)
  # extracting hash from staged roman hash
  @staged_roman_hash.each do |element|
    @output_roman << (element[:largest_element][:unit].to_s)*(element[:times])
  end
  return @output_roman
end

#convert_roman_to_decimal(input_roman = @input_string.clone) ⇒ Object

converts given arabic number (in string form) to corresponding integer



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/roman_numbers/roman_number.rb', line 66

def convert_roman_to_decimal(input_roman=@input_string.clone)
  input_roman
  # generating regex expressions
  double_units_array = ROMAN_NON_REPEATABLE_UNITS_2.map { |element| ('^' + element[:unit].to_s) }
  single_units_array = (ROMAN_REPEATABLE_UNITS + ROMAN_NON_REPEATABLE_UNITS_1).map { |element| ('^' + element[:unit].to_s) }
  double_units_regex = Regexp.new(double_units_array.join('|'))
  single_units_regex = Regexp.new(single_units_array.join('|'))
  # validation
  # TODO: to add more validations
  if input_roman =~ /(.)\1{#{MAX_ALLOWED_REPETITION},}/
    raise InvalidInputError, "Invalid Input: #{input_roman}"
  end
  # processing
  if input_roman.length > 0
    if unit = input_roman.slice!(double_units_regex)
      @output_arabic += ROMAN_DOUBLE_UNITS.find { |element| element[:unit] == unit.to_sym }[:value]
      convert_roman_to_decimal(input_roman)
    elsif unit = input_roman.slice!(single_units_regex)
      @output_arabic += ROMAN_SINGLE_UNITS.find { |element| element[:unit] == unit.to_sym }[:value]
      convert_roman_to_decimal(input_roman)
    else
      # invalud input
      raise InvalidInputError, "Invalid Input: #{input_roman}"
    end
  else
    # process is complete
    return @output_arabic
  end

end