Recursion 计算句子中奇数的数量

Recursion 计算句子中奇数的数量,recursion,lisp,scheme,sicp,Recursion,Lisp,Scheme,Sicp,我是lisp的新手,这是一个实践问题 首先,这个问题来自简单的scheme。我不知道如何回答这个问题。 这个问题的目的是编写函数,count odd,该函数将一个句子作为输入,并计算其中包含的奇数位数,如下所示: (奇数)(23455641097) 六, 或 (奇数)(24680 42 88) 0 如果可能的话,你将如何做到这一点,使用高阶函数,或递归或两者兼而有之-无论什么都可以完成任务 我会给你一些建议,而不是一个完整的解决方案: (define (count-odd num_list)

我是lisp的新手,这是一个实践问题

首先,这个问题来自简单的
scheme
。我不知道如何回答这个问题。
这个问题的目的是编写函数,
count odd
,该函数将一个句子作为输入,并计算其中包含的奇数位数,如下所示:

(奇数)(23455641097) 六,

(奇数)(24680 42 88) 0


如果可能的话,你将如何做到这一点,使用高阶函数,或递归或两者兼而有之-无论什么都可以完成任务

我会给你一些建议,而不是一个完整的解决方案:

(define (count-odd num_list)
    (if (null? num_list)
        0
        (+ (num_odds (car num_list)) (count-odd (cdr num_list)))))

(define (num_odds number)
    (if (zero? number)
        0
        (+ (if (odd? number) 1 0) (num_odds (quotient number 10)))))
首先,我看到了两种不同的方法,递归或高阶函数+递归。对于这种情况,我认为直接递归更容易实现

所以我们需要一个函数,它接受一个列表并执行一些操作,所以

(define count-odd
  (lambda (ls) SOMETHING))
这是递归的,所以我们要拆分列表

(define count-odd
  (lambda (ls)
    (let ((head (car ls)) (rest (cdr ls)))
      SOMETHING)))
现在出现了一个问题,这是一个空列表的错误(例如
(count odd'())
),但我将让您了解如何解决这个问题。提示,签出scheme的case表达式,它使检查和处理空列表变得容易

现在我们的递归是这样的:

(+ (if (is-odd head) 1 0) (Figure out how many odds are in rest))

这应该给你一些开始的东西。如果您以后有任何具体问题,请随时发布更多问题。

请首先考虑其他答案指南,以便您自己尝试。以下是一种不同的解决方法。以下是经过测试的完整解决方案:

(define (count-odd num_list)
    (if (null? num_list)
        0
        (+ (num_odds (car num_list)) (count-odd (cdr num_list)))))

(define (num_odds number)
    (if (zero? number)
        0
        (+ (if (odd? number) 1 0) (num_odds (quotient number 10)))))
这两个过程都是递归的

  • count odd
    不断获取列表的第一个元素,并将其传递给
    num_赔率
    ,直到列表中没有剩余元素(即基本情况,空列表)

  • num\u赔率
    获取数字的奇数位数。为此,始终询问数字是否为奇数,在这种情况下,它将加1,否则为0。然后将该数字除以10以删除最低有效数字(该数字决定该数字是奇数还是偶数),并作为参数传递给新调用。该过程将重复,直到数字为零(基本情况)


在跳转到更高阶的解决方案之前,尝试仅使用递归手动解决问题;为此,我建议看一下其他答案。在您完成这项工作之后,使用您可以使用的工具寻求一个切实可行的解决方案-我将把问题分为两部分

首先,如何在正整数的数字列表中拆分正整数;这是一个针对输入数字的递归过程。有几种方法可以做到这一点——首先将数字转换为字符串,或者使用算术运算提取数字,举几个例子。我将在后面使用尾部递归实现:

(define (split-digits n)
  (let loop ((n n)
             (acc '()))
    (if (< n 10)
        (cons n acc)
        (loop (quotient n 10)
              (cons (remainder n 10) acc)))))

如果其他一些解决方案看起来很奇怪,请不要感到困惑。Simply Scheme对
first
butfirst
使用非标准定义。这里有一个解决方案,我希望简单地遵循这个方案

这里有一个解决问题的策略:

  • 将数字转换为数字列表
  • 转换为零和一的列表(零=偶数,一=奇数)
  • 在列表中添加数字
示例:123->'(1 2 3)->'(1 0 1)->2

(定义(数字?x)
(数字x)
(如果(数字x)
(列表十)
(反对(余数x10)
(数字->数字(商x 10щщ)!)
(定义(数字->零/一d)
(如果(偶数d)01))
(定义(数字->零/一)
(地图数字->零/一ds)
(定义(添加数字xs)
(如果(空?xs)
0
(+(第一个xs)
(添加数字(但第一个xs(()())))
(定义(计算赔率x)
(添加数字)
(数字->零/一
(数字->数字x)))

以上内容未经测试,因此您可能需要修复一些拼写错误。

我认为这也是一个好方法

(define (count-odd sequence)
  (length (filter odd? sequence)))

(define (odd? num)
  (= (remainder num 2) 1))

(count-odd '(234 556 4 10 97))
希望这会有所帮助~

(长度序列)将返回序列的长度,
(filter proc sequence)将返回一个序列,其中包含满足该过程的所有元素。

您可以定义一个名为(odd?num)

的函数。该过程将整数列表作为其输入,而不是简单的模式a中的“句子”句子是一个列表。
(define (count-odd sequence)
  (length (filter odd? sequence)))

(define (odd? num)
  (= (remainder num 2) 1))

(count-odd '(234 556 4 10 97))