找到素因太慢或崩溃

时间:2016-11-22 20:58:18

标签: optimization lisp common-lisp

我目前正在通过浏览ProjectEuler网站上的一些问题来学习LISP。其中一个问题是:

  

13195的主要因素是5,7,13和29。

     

600851475143号码的最大主要因素是什么?

我已经废弃了执行此操作的Lisp代码。但是,对于9位以上的数字,它非常慢。大多数时候我从来没有得到解决方案,而对于8位数,它需要大约4-5秒。更重要的是,有时我会出现“超出HEAP”错误。

我的问题是我在运行代码方面做错了什么(使用Aquamacs)?有哪些方法可以优化此代码以更好地适应手头的任务?更重要的是,如何避免“超过HEAP”崩溃?

代码:

(defun potential-factors (number) 
  (loop for x from 1 to (ceiling (/ number 2)) 
        for y = x 
        collect y))

(defun factors (number) 
  (let (prime-factors '()) 
    (loop for x in (potential-factors number) 
          do (if (= (mod number x) 0) 
                 (setq prime-factors (cons x prime-factors)))) 
    prime-factors))

(defun is-prime (n &optional (d (- n 1))) 
  (if (/= n 1)
      (or (= d 1)
          (and (/= (rem n d) 0)
               (is-prime  n (- d 1)))) ()))

(defun problem-3 (number) 
  (last (sort (remove-if-not #'is-prime (factors number) :from-end t) #'<)))

3 个答案:

答案 0 :(得分:2)

问题是您要在potential-factors中创建1到n / 2之间所有数字的列表。该列表占用大量内存并导致程序崩溃。好消息是您不需要在列表中累积这些数字,而只需一次使用一个数字。在factors中,将(loop for x in (potential-factors number)替换为(loop for x from 1 to (ceiling (/ number 2))

这应该可以解决问题。

答案 1 :(得分:1)

我不是数学家,但另一个想法:将n除以2的见解似乎是因子成对出现。只有当A乘以B是N时,A才是N的因子,所以B必须至少为2.但是这个逻辑可以扩展,对吗?除以3怎么样?一旦你检查了3是否是一个因素,那么检查所有大于1/3 N的数字是没有意义的。对于4等等也是如此。观察似乎是你真的只需要检查A小于或等于B的数字 - 那么它的限制是多少?好吧,如果A = B,那么A乘以B = A乘以A,这意味着在那种情况下,A是N的平方根。所以我认为你只需要检查高达平方根N,而不是一直到N / 2.

但我不是数学家。

答案 2 :(得分:0)

您认为(potential-factors 600851475143)的结果是什么?计算结果需要多长时间,结果需要多少内存?