将数字列表分解为数字 [英] Decompose a list of numbers into digits

查看:77
本文介绍了将数字列表分解为数字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从数字列表开始创建数字列表. 例如,我想通过将列表的头除以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->numbernumber->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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆