【发布时间】:2017-10-06 00:05:49
【问题描述】:
在尝试解决 Project Euler 中的问题时,我编写了以下函数和宏:
(defun digits (n &key (base 10)) ;; Returns a list with the digits of 'n'
(if (< n base) (list n) ;; in a given base.
(multiple-value-bind (div rem)
(floor n base)
(concatenate 'list (digits div :base base) (list rem)))))
(defmacro test-palindromes (n1 n2)
(let* ((dn1 (digits n1)) (dn2 (digits n2))
(hash (loop for i in dn1 ; A-list describing digit associations
collecting (assoc i (pairlis dn2
(loop for i from 0 below (length dn1)
collecting i))))))
`(lambda (n1 n2) (and ,@(loop for i in hash
for j from 0
collecting `(char= (char n1 ,(cdr i)) (char n2 ,j)))))))
如果一个字符串对应于另一个字符串的特定排列,我想做的是生成一个返回 T 的 lambda。例如:
1 > (pprint (macroexpand-1 '(test-palindromes 1089 9801)))
(LAMBDA (N1 N2)
(AND (CHAR= (CHAR N1 3) (CHAR N2 0))
(CHAR= (CHAR N1 2) (CHAR N2 1))
(CHAR= (CHAR N1 1) (CHAR N2 2))
(CHAR= (CHAR N1 0) (CHAR N2 3))))
1 >
当输入是整数时它工作正常...
1 > (funcall (test-palindromes 1089 9801) "ALAS" "SALA")
T
1 > (funcall (test-palindromes 1089 9801) "ALAS" "SALE")
Nil
...但是如果我尝试给它更复杂的输入,就会失败:
1 > (setf g 10)
10
1 > (funcall (test-palindromes 1089 (+ 9791 g)) "ALAS" "SALA")
> Error: The value (+ 9791 G) is not of the expected type REAL.
> While executing: CCL::<-2, in process listener(1).
> Type :POP to abort, :R for a list of available restarts.
> Type :? for other options.
2 >
无奈之下,尝试了一个笨拙的解决方案,将dn1 和dn2 设置为(eval (digits dn1)) 和(eval (digits dn2))。这产生了部分改善...
2 > (funcall (test-palindromes 1089 (+ 9791 g)) "ALAS" "SALA")
T
...但是这段代码仍然失败:
(loop for pos from 0 to 66
nconcing (loop for i in (nthcdr (1+ pos) 4-digits)
for j from 0
when (equal (sort (digits (nth pos 4-digits)) #'<)
(sort (digits i) #'<))
collect (test-palindromes (nth pos 4-digits) i)))
> Error: Unbound variable: POS
> While executing: CCL::CHEAP-EVAL-IN-ENVIRONMENT, in process listener(1).
> Type :GO to continue, :POP to abort, :R for a list of available restarts.
> If continued: Retry getting the value of POS.
> Type :? for other options.
3 >
(变量 4-digits 包含所有 4 位完美正方形的有序列表。)
我想应该得到eval'ed 的东西被跳过了,但我并没有真正理解循环中发生了什么。为什么pos 不再被识别?这个循环可以工作吗?任何意见表示赞赏。
谢谢, 保罗
【问题讨论】:
标签: lambda macros common-lisp