通过Chris Pine的学习编程并开始编号到罗马数字转换项目。下面的代码可以工作,但是如果(和结束)语句的话,这些代码都非常难看。但是,当我使用elsif时程序没有响应(似乎冻结)。任何想法都会有所帮助!
def calc input
roman_numeral = ''
while true
if input >= 1000
roman_numeral += 'M' * (input / 1000)
input = input - (1000 * (input / 1000))
if input <= 999 || input >= 500
roman_numeral += 'D' * (input / 500)
input = input - (500 * (input / 500))
if input <= 499 || input >= 100
roman_numeral += 'C' * (input / 100)
input = input - (100 * (input / 100))
if input <= 99 || input >= 50
roman_numeral += 'L' * (input / 50)
input = input - (50 * (input / 50))
if input <= 49 || input >= 10
roman_numeral += 'X' * (input / 10)
input = input - (10 * (input / 10))
if input <= 9 || input >= 5
roman_numeral += 'V' * (input / 5)
input = input - (5 * (input / 5))
if input <= 4 || input >= 1
roman_numeral += 'I' * (input / 1)
input = input - (1 * (input / 1))
puts roman_numeral
break
end
end
end
end
end
end
end
end
end
puts 'Give me a number, any number:'
input = gets.chomp.to_i
calc(input)
答案 0 :(得分:3)
将方法Enumerable#find与数组一起使用很方便:
ARR = [[1000,'M'], [ 500,'D'], [100,'C'], [50,'L'], [10,'X'], [5,'V'], [1,'I']]
def which(input)
ARR.find { |v,_| input >= v }
end
which(2) #=> [1, "I"]
which(7) #=> [5, "V"]
which(17) #=> [10, "X"]
which(77) #=> [50, "L"]
which(777) #=> [500, "D"]
which(7777) #=> [1000, "M"]
假设您要将整数转换为罗马数字,请考虑使用方法Fixnum#divmod。假设整数是2954
,并且您已经确定有两个"M"
和一个"D"
(因此您的罗马数字字符串的开头是{{ 1}}),"MMD"
遗留下来。然后:
454
告诉您剩下c, rem = 454.divmod(100)
#=>[4, 54]
c #=> 4
rem #=> 54
的{{1}}有四个。
然而,有四个"C"
被写为54
(而非"C"
),因此您可能需要使用以下哈希值:
"CD"
将"CCCC"
&#39;的数量转换为罗马数字。在这里,您可以将REP = {..., "C"=>["C", "CC", "CCC", "CD"], ...}
追加到"C"
:REP["C"][4-1] #=> "CD"
。
答案 1 :(得分:1)
Cary Swoveland的答案是减少if
块嵌套的绝佳方法。
他的回答告诉你下一个数字,但不是多少(如你的代码中)。将它组合在一起的一种自然方法是使用递归函数调用:
class Romans
def self.calc(input, acc = "")
raise ArgumentError.new("Roman Numerals must be positve") if input < 0
raise ArgumentError.new("Roman Numerals must be integers") if ! input.is_a? Integer
return acc if input == 0
amount, numeral = which(input)
acc += numeral
input -= amount
calc(input, acc)
end
@@ARR = [[1000,'M'], [ 500,'D'], [100,'C'], [50,'L'], [10,'X'], [5,'V'], [1,'I']]
def self.which(input)
@@ARR.find { |v,_| input >= v }
end
end
使用中:
pry(main)> (1..10).each{|i| puts "#{i}=> #{Romans.calc(i)}"}
1=> I
2=> II
3=> III
4=> IIII
5=> V
6=> VI
7=> VII
8=> VIII
9=> VIIII
10=> X
pry(main)> [Random.rand(1..100000)].each{|i| puts "#{i}=> #{Romans.calc(i)}"}
63124=> MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMCXXIIII
请注意,ruby没有TCO,因此会使堆栈数量足够大 - 但如果您需要800万的罗马数字版本,您可能需要编写一些新的字母。
答案 2 :(得分:0)
这是一个使用字符串乘法的。例如:('M'* 3)='MMM'
def to_roman(number)
raise 'Must use positive numbers.' if number <= 0
roman = ''
roman << 'M' * (number / 1000)
roman << 'D' * (number % 1000 / 500)
roman << 'C' * (number % 500 / 100)
roman << 'L' * (number % 100 / 50)
roman << 'X' * (number % 50 / 10)
roman << 'V' * (number % 10 / 5)
roman << 'I' * (number % 5 / 1)
roman
end
puts to_roman(1234) # <-- test
参考:学习Chris Pine的第二课程