我目前正在通过浏览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) #'<)))
答案 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)
的结果是什么?计算结果需要多长时间,结果需要多少内存?