优化Project Euler 12的简单r代码

时间:2017-08-31 03:00:45

标签: r

项目欧拉问题12的想法是找到具有指定数量的除数(https://projecteuler.net/problem=12)的最小三角数。为了解决这个问题,我编写了以下代码:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input type="text" class="question" placeholder="multipleChoice"><br><br>
<input type="text" class="question" placeholder="trueFalse"><br><br>
<input type="text" class="question" placeholder="shortAnswer"><br><br>
<input type="text" class="question" placeholder="shortAnswer"><br><br>
<input type="text" class="question" placeholder="description"><br><br>
<input type="text" class="question" placeholder="multipleChoice"><br><br>
<input type="text" class="question" placeholder="multipleChoice"><br><br>
<input type="text" class="question" placeholder="trueFalse"><br><br>
<input type="text" class="question" placeholder="trueFalse"><br><br>
<input type="text" class="question" placeholder="multipleChoice"><br><br>
<input type="text" class="question" placeholder="multipleChoice"><br><br>

<span id="result"></span>

# This function finds the number of divisors of a number and returns it. 
FUN <- function(x) {
    i = 1
    lst = integer(0)
    while(i<=x)
    {
        if(x %% i ==0)
        {
          lst = c(lst, i)
        }
      i = i +1
    }

  return(lst)
}

此代码为少数较小的测试用例提供了正确答案:n = 1 i=1 while (length(FUN(n))<500) { i = i + 1 n = n + i } 将生成length(FUN(n))<46将生成length(FUN(n))<6

但是,这个简单易用的代码需要24小时才能运行(并且仍在运行)28。我知道对于一个有500个除数的数字,这个数字可能非常大,但我想知道为什么 所以 很长时间才能运行。

2 个答案:

答案 0 :(得分:2)

FUN对于这项任务来说效率太低了。由于第一个三角形数字高于12,000,数值为75,000,000,FUN贯穿所有这些数字......要执行的迭代次数几乎为

12000 * 75000000 / 2 = 450 * 10^9

这显然不仅仅是R在一个合理的时间范围内相对缓慢的循环。

相反,您可以应用数字包中使用素数因子分解的divisors函数。以下代码需要大约5-6秒(在我的机器上)才能找到三角形数字。

library(numbers)

t <- 0
system.time(
    for (i in 1:100000) {
        t <- t + i
        d <- length( divisors(t) )
        if (d > 500) {
            cat(i, t, d, '\n')
            break
        }
    }
)
## 12375 76576500 576 
##    user  system elapsed 
##   5.660   0.000   5.658 

不是计算第i个三角形数字,而是将i添加到最后一个三角形数字。节省的时间很少。

答案 1 :(得分:1)

这是我的尝试:

library(gmp)
library(plyr)

get_all_factors <- function(n)
{
  prime_factor_tables <- lapply(
    setNames(n, n), 
    function(i)
    {
      if(i == 1) return(data.frame(x = 1L, freq = 1L))
      plyr::count(as.integer(gmp::factorize(i)))
    }
  )
  lapply(
    prime_factor_tables, 
    function(pft)
    {
      powers <- plyr::alply(pft, 1, function(row) row$x ^ seq.int(0L, row$freq))
      power_grid <- do.call(expand.grid, powers)
      sort(unique(apply(power_grid, 1, prod)))
    }
  )
}

for (i in 99691200:100000) {
  if (length(get_all_factors(i)[[1]])>500) print(paste(i, length(get_all_factors(i)[[1]])))
  if (i %% 100000 == 0) print(paste("-",i,"-"))
}

只要你感到困扰就让它运行......