我正在尝试从数字列表开始创建一个数字列表。
例如,如果头部>> 10并且将1加到下一个元素,我想通过将列表的头部划分为10来将(11 4 6)分解为(1 5 6)。
我的代码看起来像这样
(defun createparameters (l)
(cond ((null l) l)
((> 9 (car l)) (setf (car l) (mod (car l ) 10))
(setf (cadr l) (+ (cadr l) 1)))
(t (createparameters (cdr l)))))
但它不会改变我的引用列表。 非常感谢帮助。
答案 0 :(得分:2)
如果第一个元素大于9,你写道你想要完成操作,但在你的代码中,你正在做相反的事情。 (> 9 (car l))
与中缀9 > (car l)
相同,因此当第一个元素为8或更低时,您可以执行此操作。
以下是代码的功能版本,它继续处理下一个子列表:
(defun createparameters (l)
(cond ((null l) l)
((and (consp l) (< 9 (car l)))
(cons (mod (car l ) 10)
(createparameters
(cons (+ (cadr l) 1)
(cddr l)))))
(t (cons (car l)
(createparameters (cdr l))))))
(defparameter test (list 11 11 2 3))
(setf test (createparameters test))
test ; ==> (1 2 3 3)
这是一个经过修改的变异版本(类似于您的代码):
(defun createparameters (l)
(cond ((null l) l)
((< 9 (car l)) (setf (car l) (mod (car l ) 10))
(setf (cadr l) (+ (cadr l) 1))
(createparameters (cdr l)))
(t (createparameters (cdr l)))))
(defparameter test (list 11 11 2 3))
(createparameters test)
test ; ==> (1 2 3 3)
我开始怀疑这是否是一个进位,因此第一个元素是最低有效数字,最后一个是最高数字。如果只是这样,只有添加一个只有在数字总是低于20时才能工作,如果最后一个数字变为10或更高,代码将不起作用。
答案 1 :(得分:1)
这是一个直接执行任务的版本。
(defun decompose (digits)
"Given a list of digits (least-significant digit first), return a
list of normalized digits, i.e., where each digit is less than 10."
(do ((digits digits (rest digits)) ; iterate through the digits.
;; There's no initial digit, and the carry is initially 0.
(carry 0) (digit)
;; The result starts as '(), and adds a digit on each successive
;; iteration, where the digit is computed in the loop body.
(result '() (list* digit result)))
;; End when there are no digits left. Most of the result is
;; simply the reversed result, but if there's a non-zero carry
;; at the end, put it into a list and decompose it, too.
((endp digits)
(nreconc result (if (zerop carry) '()
(decompose (list carry)))))
;; At each iteration, add the first digit to the carry, and divide
;; by 10. The quotient is the carry for the next iteration, and
;; the remainder is the digit that's added into the results.
(multiple-value-setq (carry digit)
(floor (+ carry (first digits)) 10))))
(decompose '(10005 2 3))
;=> (5 2 3 0 1)
(decompose '(11 2 4))
;=> (1 3 4)
(decompose '(23 0))
;=> (3 2)
(decompose '(11 11 4 6))
;=> (1 2 5 6)
更模块化的方法可能会将其分解为两部分。首先,给定一个数字列表,每个数字可能大于9,我们可以将原始数字重建为数字(即,不是数字列表)。这非常简单:
(defun digits->number (digits)
(reduce (lambda (digit number)
(+ digit (* 10 number)))
digits
:from-end t))
(digits->number '(1 2 3 4))
;=> 4321
(digits->number '(205 3))
;=> 235
现在,将数字转换为数字列表也不会太难。
(defun number->digits (number)
(do ((digit)
(digits '() (list* digit digits)))
((zerop number) (nreverse digits))
(multiple-value-setq (number digit)
(floor number 10))))
(number->digits 1024)
;=> (4 2 0 1)
(number->digits 8923)
;=> (3 2 9 8)
现在,我们可以观察digits->number
将数字列表转换为我们需要的表单中的数字,即使存在&#39;数字&#39;大于9的number->digits
始终生成一个所有数字都小于10的表示。因此,我们也可以将decompose
实现为number->digits
的{{1}}。
digits->number
(defun decompose (digits)
(number->digits (digits->number digits)))
作为一个有趣的观察,我认为你可以说(decompose '(10005 2 3))
;=> (5 2 3 0 1)
(decompose '(11 2 4))
;=> (1 3 4)
(decompose '(23 0))
;=> (3 2)
(decompose '(11 11 4 6))
;=> (1 2 5 6)
的输入空间是非负整数的列表,并且每个小于10的非负整数列表是修复的decompose
的点。