[RUBY] roman numerals

!Ubuntu-20.04.1!ruby-2.7.1p83

theme

Write a method that takes arabic numerals and returns roman numerals

Roman numerals are a combination of symbols

Roman numerals seem to be able to express 1,5,10,50,100,500,1000 with one letter, and express numbers with that combination.
Then, I thought that I should just divide the received number from the larger number. First of all, I wrote it all at once

def roman_numerals(num)
  m, modulo = div(num,1000)
  d, modulo = div(modulo,500)
  c, modulo = div(modulo,100)
  l, modulo = div(modulo,50)
  x, modulo = div(modulo,10)
  v, modulo = div(modulo,5)

  val = 'M' * m + 'D' * d + 'C' * c + 'L' * l + 'X' * x + 'V' * v + 'I' * modulo
  return val
end

def div(num, waru)
  div = num / waru
  modulo = num % waru

  return div, modulo
end

[1,2,4,5,6,9,10,11,14,15,19,38,42,49,51,97,99,439,483,499,732,961,999,1999].each do |number|
  puts "#{number} : #{roman_numerals(number)}"
end

result

1 : I
2 : II
4 : IIII
5 : V
6 : VI
9 : VIIII
10 : X
11 : XI
14 : XIIII
15 : XV
19 : XVIIII
38 : XXXVIII
42 : XXXXII
49 : XXXXVIIII
51 : LI
97 : LXXXXVII
99 : LXXXXVIIII
439 : CCCCXXXVIIII
483 : CCCCLXXXIII
499 : CCCCLXXXXVIIII
732 : DCCXXXII
961 : DCCCCLXI
999 : DCCCCLXXXXVIIII
1999 : MDCCCCLXXXXVIIII

Do you think this is complete? However, it is good that the Roman numeral
3 is III and 38 is XXXVIII. However, 4 is IV, 9 is IX, and 99 is XCIX. Who came up with such annoying numbers

4 and 9 are exceptions

I've been studying Roman numerals rather than a program, but the keys to understanding this confusing rule are "4" and "9". As mentioned above, 4 is IV (5-1) and 9 is IX (10-1). 4 and 9 have a structure in which the fraction I comes to the left of the basic numbers V and X, and the fraction is drawn from the basic numbers
, so 14 is XIV (10+ (5-1)). , 42 is XLII ((50-10) +2), 49 is XLIX ((50-10) + (10-1)). Note that 49 is not IL (50-1). Similarly, 99 is XCIX ((100-10) + (10-1)) instead of IC (100-1). It's complicated
In other words, it seems quite so if you calculate it digit by digit.

def roman_numerals(num)
  m, modulo  = calcDiv(num,1000)
  d, modulo, cm = calcDiv(modulo,500)
  c, modulo, cd = calcDiv(modulo,100)
  l, modulo, xc = calcDiv(modulo,50)
  x, modulo, xl = calcDiv(modulo,10)
  v, modulo, ix = calcDiv(modulo,5)
  i, modulo, iv = calcDiv(modulo,1)

  val = 'M' * m + 'CM' * cm + 'D' * d + 'CD' * cd + 'C' * c + 'XC' * xc + 'L' * l + 'XL' * xl + 'X' * x + 'IX' * ix + 'V' * v + 'IV' * iv + 'I' * i
  return val
end

def calcDiv(num, waru)
  div = num / waru
  modulo = num % waru
  reigai = 0

  if waru == 500
    if div == 1 and num - 900 >= 1
      div = 0
      reigai = 1
    end
  elsif waru == 100
    if div == 4
      div = 0
      reigai = 1
    end
  elsif waru == 50
    if div == 1 and num - 90 >= 1
      div = 0
      reigai = 1
    end
  elsif waru == 10
    if div == 4
      div = 0
      reigai = 1
    end
  elsif waru == 5
    if div == 1 and num == 9
      div = 0
      reigai = 1
    end
  elsif waru == 1
    if div == 4
      div = 0
      reigai = 1
    end
  end

  return div, modulo, reigai
end

It's a dirty code, but I used it as a variable to judge whether the variable called reigai has an exceptional notation of 4 or 9. For the time being, this should have divided the conditions. Run.

1 : I
2 : II
4 : IV
5 : V
6 : VI
9 : IXIV
10 : X
11 : XI
14 : XIV
15 : XV
19 : XIXIV
38 : XXXVIII
42 : XLII
49 : XLIXIV
51 : LI
97 : XCXLVII
99 : XCXLIXIV
439 : CDXXXIXIV
483 : CDLXXXIII
499 : CDXCXLIXIV
732 : DCCXXXII
961 : CMCDLXI
999 : CMCDXCXLIXIV
1999 : MCMCDXCXLIXIV

Hmm? Something is wrong. The funny ones are 9, 19, 49, 97, 99, 439, 499, 961, 999, 1999. In other words, something is happening with 9 entanglements.
If you look closely, 9 wants IX to come out, but IV is extra. 19 is the same. In other words, 4 is extra.
The more you review the program, for example, it is good to call calcDiv on the 7th line and make an exceptional notation (IX) when it is 9, but the place where you should finish the process is as follows. I went to the line and called calcDiv again, and the answer of 9% 5 is 4, so I have to write IV! Because it is, before the val of roman \ _numerals

 if cm == 1
   cd = 0
 end
 if xc == 1
   xl = 0
 end
if ix == 1
   iv = 0
 end

I added, and when it was decided to write 9 in each place, I defined that 4 should not be written anymore. Then

1 : I
2 : II
4 : IV
5 : V
6 : VI
9 : IX
10 : X
11 : XI
14 : XIV
15 : XV
19 : XIX
38 : XXXVIII
42 : XLII
49 : XLIX
51 : LI
97 : XCVII
99 : XCIX
439 : CDXXXIX
483 : CDLXXXIII
499 : CDXCIX
732 : DCCXXXII
961 : CMLXI
999 : CMXCIX
1999 : MCMXCIX

I was able to output properly. How did you see the ancient Romans? I don't have enough physical strength for refactoring, so please forgive me here.

Reference article


Recommended Posts

roman numerals
roman numerals
roman numerals
roman numerals
roman numerals
roman numerals
Roman Numerals
roman numerals
roman numerals
EX1: roman numerals
Let's solve the roman numerals
Find Roman numerals in Ruby
Convert numbers to Roman numerals in Ruby
roman numerals (I tried to simplify it with hash)