2

我需要一个用 scheme 编写的程序的子例程,它接受一个整数,比如 34109,并将其放入一个包含元素 3、4、1、0、9 的列表中。整数可以是任意长度。有人对此有诀窍吗?我考虑过在每个地方都使用模数,但我认为它不应该那么复杂。

4

3 回答 3

4

我能想到的最简单的方法是使用算术运算和一个命名let来实现尾递归:

(define (number->list num)
  (let loop ((num num)
             (acc '()))
    (if (< num 10)
        (cons num acc)
        (loop (quotient num 10)
              (cons (remainder num 10) acc)))))

或者,您可以使用字符串操作来解决此问题:

(define char-zero (char->integer #\0))

(define (char->digit c)
  (- (char->integer c) char-zero))

(define (number->list num)
  (map char->digit
       (string->list (number->string num))))

这可以压缩成一个函数,但我相信如果我们将问题分成上面的子部分会更容易理解。

(define (number->list num)
  (map (lambda (c) (- (char->integer c) (char->integer #\0)))
       (string->list
        (number->string num))))

无论如何,结果如预期:

(number->list 34109)
> '(3 4 1 0 9)
于 2012-10-11T14:30:21.900 回答
2

像这样的东西:

(define (num2list-helper num lst)
  (cond ((< num 10) (cons num lst))
        (else (num2list-helper (floor (/ num 10)) (cons (modulo num 10) lst)))))

(define (num2list num)
  (num2list-helper num '()))

(num2list 1432)

正如 itsbruce 评论的那样,您可以在主函数中隐藏辅助函数:

(define (num2list num)
  (define (num2list-helper num lst)
    (cond ((< num 10) (cons num lst))
          (else (num2list-helper (floor (/ num 10)) (cons (modulo num 10) lst)))))

    (num2list-helper num '()))

(num2list 1432)

待续...

于 2012-10-11T10:43:51.060 回答
0

我不喜欢手动循环,所以这里有一个基于展开的解决方案(首先加载SRFI 1SRFI 26):

(define (digits n)
  (unfold-right zero? (cut modulo <> 10) (cut quotient <> 10) n))

不过,这会返回一个 0 的空列表。如果您希望它返回(0),我们添加一个特殊情况:

(define (digits n)
  (case n
   ((0) '(0))
   (else (unfold-right zero? (cut modulo <> 10) (cut quotient <> 10) n))))

当然,您可以将其推广到其他基础。在这里,我使用可选参数来实现它,所以如果你不指定基数,它默认为 10:

(define (digits n (base 10))
  (case n
   ((0) '(0))
   (else (unfold-right zero? (cut modulo <> base) (cut quotient <> base) n))))

不同的 Scheme 实现对可选参数使用不同的语法;以上使用 Racket 样式(和/或SRFI 89样式)语法。

于 2012-10-11T20:55:09.473 回答