我目前正在处理Project Euler中的一些问题,这是我的Common 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))
#'<))))
答案 0 :(得分:3)
正如High Performance Mark的评论所述,所以可以关闭此问题:
我做得不好,导致计算花费这么长时间?
您进行n!
次计算,n
为多位数。 1000000!
大约等于8.26×10 5565708 (请参阅Quora以获得一个很好的解释),所以难怪你的计算机无法处理它;)
我是否遇到了Lisp实现(SBCL)的一些限制?
也许,但你的RAM很可能首先失败。
可以采取哪些措施让计算在合理的时间内完成?
做另一个计算。项目欧拉演习的重点通常是找到一种解决问题的聪明方法,而不是强力解决问题。