将数字列表分解为数字 [英] Decompose a list of numbers into digits
问题描述
我正在尝试从数字列表开始创建数字列表. 例如,我想通过将列表的头除以10(如果头> = 10并在下一个元素上加1),将(11 4 6)分解为(1 5 6). 我的代码看起来像这样
I am trying to create a list of digits starting from a list of numbers.
For example I want to break (11 4 6) into (1 5 6) by dividing the head of the list to 10 if the head is >= 10 and adding 1 to the next element.
My code looks like this
(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)))))
但它不会更改我的引用列表. 帮助将不胜感激.
but it does not change my referenced list. Help would be greatly appreciated.
推荐答案
直接方法
这里是直接执行任务的版本.
A direct approach
Here's a version that performs the task directly.
(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,我们可以将原始数字重构为数字(即,不重构为数字列表).这很简单:
A modular approach
A more modular approach might break this down into two parts. First, given a list of digits, each of which might be greater than 9, we can reconstruct the original number as a number (i.e., not as a list of digits). This is pretty straightforward:
(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
现在,将数字转换为数字列表也不太困难.
Now, converting a number into a list of digits isn't too hard either.
(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
将数字列表转换为所需形式的数字,即使存在大于9的数字"也是如此.number->digits
始终生成表示所有数字的表示形式小于10.因此,我们也可以将decompose
实现为digits->number
的number->digits
.
Now, we can observe that digits->number
converts the digits list into the number in the form that we need, even when there are 'digits' that are greater than 9. number->digits
always produces a representation where all the digits are less than 10. Thus, we can also implement decompose
as number->digits
of 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)
作为一个有趣的观察,我认为您可以说decompose
的输入空间是非负整数的列表,每个小于10的非负整数的列表都是一个不动点<decompose
的/em>.
As an interesting observation, I think you can say that the space of input for decompose
is lists of non-negative integers, and that each list of non-negative integers less than 10 is a fixed point of decompose
.
这篇关于将数字列表分解为数字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!