Ruby方法返回意外值

时间:2014-08-14 14:52:39

标签: ruby algorithm

我有一种方法可以返回由两个3位数字的乘积组成的最大回文,该数字小于smaller_than。它应该尽可能快地运行。

回文数字两种方式相同。由两个3位数字组成的最小回文是101101,这是143 * 707的乘积。

这是我的代码:

def palindrome(smaller_than)
  max = 0

  999.downto(143).each do |x|
    999.downto(707).each do |y|
      break if (max > x * y) || (smaller_than < x * y)
      max = x * y if x * y == (x * y).to_s.reverse.to_i
    end
  end

  return max
end

t = Time.now
puts palindrome(800000)
puts "Took #{Time.now-t}"

这为我723327而不是793397

如果我将代码更改为:

def palindrome(smaller_than)
  max = 0

  999.downto(143).each do |x|
    999.downto(707).each do |y|
      break if max > x * y
      max = x * y if (x * y == (x * y).to_s.reverse.to_i) && (smaller_than > x * y)
    end
  end

  return max
end

t = Time.now
puts palindrome(800000)
puts "Took #{Time.now-t}"

...它给了我793397的正确价值。

第二种方法有效,但速度太慢。为什么更快的第一种方法返回错误的值?

1 个答案:

答案 0 :(得分:0)

你的第一个版本的问题在于它不应该从内循环中断开。这是一个工作版本,几乎与非工作版本一样快。

def palindrome2(smaller_than)
  max = 0

  999.downto(143).each do |x|
    999.downto(707).each do |y|
      product = x * y
      break if max > product
      next if smaller_than < product
      max = product if product.to_s == product.to_s.reverse
    end
  end

  return max
end

此外,

如果只是重新排列支票中的条件,您可以获得相同的加速,以启用short-circuiting

  # max = x * y if (x * y == (x * y).to_s.reverse.to_i) && (smaller_than > x * y)
  max = x * y if (smaller_than > x * y) && (x * y == (x * y).to_s.reverse.to_i)