首先,对于那些不了解(或忘记)Lychrel数字的人,这里有来自维基百科的条目:http://en.wikipedia.org/wiki/Lychrel_number。
我想在0到10_000的范围内实现Lychrel数字检测器。这是我的解决方案:
class Integer
# Return a reversed integer number, e.g.:
#
# 1632.reverse #=> 2361
#
def reverse
self.to_s.reverse.to_i
end
# Check, whether given number
# is the Lychrel number or not.
#
def lychrel?(depth=30)
if depth == 0
return true
elsif self == self.reverse and depth != 30 # [1]
return false
end
# In case both statements are false, try
# recursive "reverse and add" again.
(self + self.reverse).lychrel?(depth-1)
end
end
puts (0..10000).find_all(&:lychrel?)
此代码的问题是深度值[1]。所以,基本上,depth是一个值,它定义了我们需要多少次进行迭代过程,当然,当前的数字实际上是一个Lychrel数。默认值是30次迭代,但我想添加更多的纬度,因此程序员可以通过方法的参数指定自己的深度。 30次迭代非常适合我需要的小范围,但如果我想覆盖所有自然数,我必须更敏捷。
由于递归,它在Integer#lychrel?中占有一席之地,我不能敏捷。如果我向lychrel?
提供了一个参数,那么由于[1]语句就不会有任何变化。
所以,我的问题听起来像这样:“我如何重构我的方法,所以它会正确接受参数?”。
答案 0 :(得分:2)
您目前拥有的内容称为tail recursion。这通常可以重写为循环来消除递归调用并消除堆栈空间不足的风险。尝试更像这样的东西:
def lychrel?(depth=30)
val = self
first_iteration = true
while depth > 0 do
# Return false if the number has become a palindrome,
# but allow a palindrome as input
if first_iteration
first_iteration = false
else
if val == val.reverse
return false
end
# Perform next iteration
val = (val + val.reverse)
depth = depth - 1
end
return true
end
我没有在这台机器上安装Ruby,所以我无法验证这是否100%正确,但你明白了。另外,我假设and depth != 30
位的目的是允许将回文提供为输入而不立即返回false
。
通过循环,您可以使用状态变量first_iteration
来跟踪是否需要进行val == val.reverse
检查。使用递归解决方案,作用域限制会阻止您轻松跟踪(您必须添加另一个函数参数并依次将状态变量传递给每个递归调用)。
答案 1 :(得分:1)
更干净,更像红宝石的解决方案:
class Integer
def reverse
self.to_s.reverse.to_i
end
def lychrel?(depth=50)
n = self
depth.times do |i|
r = n.reverse
return false if i > 0 and n == r
n += r
end
true
end
end
puts (0...10000).find_all(&:lychrel?) #=> 249 numbers
答案 2 :(得分:0)
bta的解决方案有一些更正:
class Integer
def reverse
self.to_s.reverse.to_i
end
def lychrel?(depth=30)
this = self
first_iteration = true
begin
if first_iteration
first_iteration = false
elsif this == this.reverse
return false
end
this += this.reverse
depth -= 1
end while depth > 0
return true
end
end
puts (1..10000).find_all { |num| num.lychrel?(255) }
不是那么快,但它确实有效:
code/practice/ruby% time ruby lychrel.rb > /dev/null
ruby lychrel.rb > /dev/null 1.14s user 0.00s system 99% cpu 1.150 total