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