好的,我上学期考了scheme,我知道你不可能在一个学期内把scheme搞得这么好。一位朋友问我如何计算某个数字出现在一个数字中的次数。如果它是一个列表,我知道该怎么做。起初我认为这是对内建商或余数的简单使用,但最终并没有像我想象的那样。例如,我如何计算数字中出现五的次数: (numfives 125458563) 应该返回 3。感谢任何帮助。
Ps:我不是在帮助他的硬件,我是为自己做的。我喜欢挑战。
用于将string->list
字符串转换为字符列表。然后像处理列表一样继续操作,您说您已经知道该怎么做。(您可以使用各种格式化函数将数字转换为字符串。)
我不喜欢所有基于字符串的解决方案。
在我看来,最好的方法是在每个阶段通过将(和修改)除以 10 来查看每个数字,然后进行比较。例子:
(define (count-digit num digit)
(let loop ((num num)
(count 0))
(if (zero? num) count
(loop (quotient num 10)
(+ count (if (= digit (remainder num 10)) 1 0))))))
这是一种可能的方法:将参数转换为字符列表,并计算与作为参数接收number
的字符对应的字符的数量:digit
(define (num-digits number digit)
(let ((n (number->string number))
(d (integer->char (+ (char->integer #\0) digit))))
(count (lambda (x) (char=? x d))
(string->list n))))
编写上述过程的另一种方法,更短但更难阅读:
(define (num-digits number digit)
(count (curry char=? (integer->char (+ (char->integer #\0) digit)))
(string->list (number->string number))))
另一种选择是通过算术运算依次处理每个数字,如@ChrisJester-Young 的回答,但考虑到数字和数字都为零的边缘情况,并避免重新定义内置 -在count
过程中 - 还要记住,这仅适用于整数 >= 0 和以 10 为底的整数。方法如下:
(define (num-digits number digit)
(if (= number digit 0)
1
(let loop ((num number)
(counter 0))
(cond ((zero? num)
counter)
((= digit (remainder num 10))
(loop (quotient num 10) (add1 counter)))
(else
(loop (quotient num 10) counter))))))
上面基于字符串的解决方案可能看起来有点笨拙,但编写起来更短,并且具有处理负数、带小数的数字、与 10 不同的基数等的额外优势。无论如何,这将适用于任何版本:
(num-digits 125458563 5)
> 3
这将适用于基于字符串的版本:
(num-digits -123.1234152 1)
> 3
将数字转换为列表,然后找出数字出现在数字中的次数。将数字转换为列表请参阅此示例。