【问题标题】:Multiplying Elements in a List Containing Pairs将包含对的列表中的元素相乘
【发布时间】:2013-09-21 21:06:48
【问题描述】:

我正在尝试使用 Scheme 编写代码(函数):

  • 将任意大小的列表作为参数
  • 将列表中的每个数字相乘
  • 应跳过符号
  • 对中的值应包含在乘法中

换句话说,结果应该如下:

> (mult '(1 2 3))
6
> (mult '(1 2 x 3 4))
24
> (mult '(1 2 z (3 y 4)))
24 (mine gives me 2)

我的代码允许我跳过符号并将所有内容相乘。但是,一旦我在列表中包含一对,它就好像它不是一个数字,因此就好像它不存在一样。这是我的代码:

(define mult
       (lambda (x)
               (if (null? x)
                      1
                      (if(number? (car x))
                         (* (car x) (mult (cdr x)))
                         (mult(cdr x))))))

我尝试在找到一对时使用 append,但显然我做错了...任何关于如何让它在一对中包含值的帮助将不胜感激。

即'(1 2 y (3 z 4) = 1 * 2 * 3 * 4

【问题讨论】:

  • 这对可以嵌套多深?有可能有这样的清单吗? '(((1)) 2)

标签: list recursion scheme multiplication


【解决方案1】:

您快到了,只是错过了清单?测试:

(define (mult lst)
  (if (null? lst) 
      1
      (let ((ca (car lst)))
        (cond
          ((number? ca) (* ca (mult (cdr lst))))
          ((list? ca)   (* (mult ca) (mult (cdr lst))))
          (else         (mult (cdr lst)))))))

编辑

他是一个没有 let 的等效版本:

(define (mult lst)
  (cond
    ((null? lst)         1)
    ((number? (car lst)) (* (car lst) (mult (cdr lst))))
    ((cons? (car lst))   (* (mult (car lst)) (mult (cdr lst))))
    (else                (mult (cdr lst)))))

如您所见, (car lst) 可能会被多次评估,因此我在第一个版本中使用了 let 来避免这种情况。

【讨论】:

  • 太棒了,谢谢!我不得不改变“名单?” “缺点?”但是,因为显然它不识别列表?作为一个功能和......我认为“缺点?”做同样的事情(如果我错了,请纠正我)。这似乎是我们一直用来声明列表的东西。但是,是的,我认为在列表乘法中使用“ca”是很重要的部分。再次感谢!
  • @Sean 你写“that ca”的方式让我觉得这部分对你来说仍然是模糊的。我编辑了我的帖子以获得一个可能更清晰的版本,没有让。
【解决方案2】:

这是一种稍微先进的技术,但这个问题可以很容易地表述为尾递归算法。

(define (mult lst)
  (let multiplying ((lst lst) (r 1))   ; r is the multiplicative identity...
    (if (null? lst)
        r
        (let ((next (car lst))
              (rest (cdr lst)))
          (multiplying rest (cond ((number? next) (* next r))
                                  ((list?   next) (* (mult next) r))
                                  (else           r)))))))
> (mult '(1 2 3 a b (((((10)))))))
60

使用尾递归会影响性能,但不可否认,这不是学习的第一件事——递归才是。然而,在这种情况下,由于列表通常很长,避免每个列表元素的堆栈帧可以显着节省;使用尾调用可以避免堆栈帧。

【讨论】:

    猜你喜欢
    • 2017-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    相关资源
    最近更新 更多