我目前正在处理一些来自欧拉项目的问题,这是我常用的Lisp学习程序的一部分我不提哪个问题符合那个地方的精神。
我遇到的问题是,我的代码适用于小输入,但对于大输入则会冻结。具体来说,它冻结的数量级与获得答案所需的数量级相同,但成功运行的数量级低于该数量级。
问题描述如下:给定一组数字,形成这些数字的所有可能置换,然后对结果进行数字排序,并选择结果集的n个成员。
我将运行下面的代码如下。
例如,如果我想获得数字的第三个排列(1, 2, 3)
,我将调用:CL-USER> (number-permutations '(1 2 3) 3)213
另一个例子是:CL-USER> (number-permutations '(0 1 2 3 5) 100)50231
代码的作用是:CL-USER> (number-permutations '(0 1 2 3 5 6 7 8) 100)1283675
但是冻结(或花费太长时间)此呼叫:CL-USER> (number-permutations '(0 1 2 3 5 6 7 8 9) 1000000)
我的问题有两个方面。我做什么效率低下,导致计算需要这么长时间?我是否遇到了lisp实现(sbcl)的一些限制?怎样才能使计算在合理的时间内完成?
代码
;;; How to make permutations of a list
;;;
;;; all permutations of a list L is:
;;; for each element E in L:
;;; that element prepended to all permutations of [ L with E removed ]
(defun permutation (digits)
;if the list is null or empty, return NIL
(cond ((null digits) nil)
;if the list consists of one element, return the list of one element
((null (cdr digits)) (list digits))
; cycle through every element in list and append
; that element to all permutations of a list of elements
; with the current element removed
(t (loop for element in digits
append (mapcar (lambda (l) (cons element l))
(permutation (remove element digits)))))))
(defun list-to-number (list)
(loop for item in list for i from (- (list-length list) 1) downto 0
summing (* (expt 10 i) item)))
(defun number-permutations (digits n)
(car (nthcdr (- n 1)
(sort (loop for item in (permutation digits)
collecting (list-to-number item))
#'<))))
最佳答案
正如High Performance Mark在评论中所述,因此这个问题可以结束:
我做什么效率低下,导致计算需要这么长时间?
你做计算,n!
是一个数字。Withn
大约等于8.26×105565708(有关详细解释,请参见Quora),难怪您的计算机无法处理它;)
我是否遇到了lisp实现(sbcl)的一些限制?
也许吧,但你的内存很可能是第一个失败的东西。
怎样才能使计算在合理的时间内完成?
再做一次计算欧拉练习项目的重点通常是找到一个聪明的方法来解决问题,而不是粗暴地强迫它。
祝你好运!
关于algorithm - 常见的Lisp代码卡住或需要优化,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46833003/