Ruby 使用>;查找第一个三角形数的算法;500个因素正在放缓

Ruby 使用>;查找第一个三角形数的算法;500个因素正在放缓,ruby,algorithm,Ruby,Algorithm,这是我的算法,找到第一个大于x的三角形数。我可以把它运行到大约x=150,然后它就需要永远。我可以做些什么改变来加快速度?谢谢 def triangle_numbers_max_divisors(x) triangle_numbers = [] divisors = 0 a = 1; b = 2 until divisors > x divisors = 0 triangle_numbers.push(a)

这是我的算法,找到第一个大于x的三角形数。我可以把它运行到大约x=150,然后它就需要永远。我可以做些什么改变来加快速度?谢谢

def triangle_numbers_max_divisors(x)
    triangle_numbers = []
    divisors = 0
    a = 1; b = 2

    until divisors > x
        divisors = 0
        triangle_numbers.push(a)
        a = a + b; b += 1

        for i in 1..triangle_numbers.last
            if triangle_numbers.last % i == 0
                divisors += 1
            end
        end
    end
    triangle_numbers.last
end
我不知道是否是最新的,但重新分配阵列的空间似乎有问题。在127时,代码运行只需6秒,然后在128时跳到30秒。它又平静了一会儿


如果您使用类似于
triangle\u numbers=array.new(x)
的东西预分配数组,您将丢失简明的
.last
语法,并且必须跟踪数组索引,但代码在所有方面都以大致二次时间运行。这意味着每增加一次,它仍然会变得异常缓慢,但你对此无能为力,你不应该碰到任何奇怪的不连续性。

看起来你在试图解决所谓的高可除三角数


我曾试图改进您的代码,但不幸的是,您的解决方案本身速度慢且效率低,如果不改变方法,就无法从根本上改进。看看这一点,也看看这一点。

其他答案中已经给出了代码运行缓慢的原因。下面是一种类似Ruby的算法编码方法。大约花了10秒来解决。*

代码

def triangle_numbers_max_divisors(min_nbr_factors)
  (1..Float::INFINITY).reduce(0) do |tnbr, n|
    tnbr += n
    return tnbr if nbr_factors(tnbr) >= min_nbr_factors
    tnbr
  end
end

def nbr_factors(n)
  m = Math.sqrt(n)
  2 * 1.upto(m).count { |i| (n % i).zero? } - ((n == m * m) ? 1 : 0)
end   

p triangle_numbers_max_divisors(500) #=> 76_576_500
解释

  • 您只需要一个值,因此不需要保留除数。数一数
  • 如果
    n
    是一个完美的平方,则术语
    -((n==m*m)?1:0
    会导致
    n
    的平方根只计算一次
  • 有时您会看到
    (1..Float::INFINITY)
    写为
    (1..1.0/0)

*在最近的一款老式Macbook Pro上

您希望实现什么?您能提供一些预期的输入输出案例吗?