【问题标题】:Using racket structs for summing elements at even and odd positions使用球拍结构对偶数和奇数位置的元素求和
【发布时间】:2014-08-24 06:26:17
【问题描述】:

在课堂上,我们使用以下球拍结构为组合语言 (lanG) 编写了一个解释器。

(struct const (n))
(struct bool (b))
(struct join (e1 e2))
(struct if-then-else (b e1 e2)) 
(struct negate (e)) 
(struct add (e1 e2))
(struct multiply (e1 e2)) 
(struct head (e))   ;returns the head of the list
(struct tail (e))    ;returns the tail of the list 
(struct biggerThan (e1 e2)) 


这种语言的宏被定义为球拍函数。一个简单的例子是:

(define (threeTimes x)
   (add x (add x x)))


使用它看起来像:

(lanG (threeTimes (const 3))) 

这会产生一个答案:

(const 9)


现在我的问题。考试中有一个任务,我们必须编写一个宏 sumAtEvenAndOdd,它将对语言常量列表求和, 使用连接结构并返回由偶数位置的元素总和和元素总和组成的一对值 在奇数位置。

这样的列表的一个例子是:

(join (const 3) (join (const 2) (const 5))) ;lanG list with no null at the end

它的结果是:

(join (const 2) (const 8))

我尝试通过将列表转换为球拍列表、使用元素压缩位置、过滤列表中的奇数或偶数元素来解决此问题, 并使用这些列表的总和生成对。这行得通,但我过于复杂了。教授说解法大概有5行。

提前感谢您的帮助。

【问题讨论】:

  • 是的,它是一个过程/解释器,它解析用上述结构编写的程序。对不起,但我宁愿不发布源代码,这样我就不会惹上麻烦。我感兴趣的主要是,我将如何遍历这样的列表。通常一个列表会以 null 或其他东西结尾,这样人们就会知道何时停止对其进行递归。

标签: scheme racket


【解决方案1】:

我假设还有谓词来识别constjoin - 我们称它们为const?join?

假设我们有一个函数将列表中的所有其他项目相加,sumAtEvenAndOdd 可能如下所示:

(define (sumAtEvenAndOdd xs)
  (join (sumEveryOther (tail xs)) (sumEveryOther xs)))

然后sumEveryOther 可以这样实现:

(define (sumEveryOther x)
  (if-then-else (const? x)
                x
                (if-then-else (join? (tail x))
                              (add (head x) (sumEveryOther (tail (tail x))))
                              (head x))))

这当然不是最优的,因为它遍历列表两次,但它很短(“exam-size”)并且完全在 lanG 中实现。

一个稍长的解决方案,只遍历列表一次,使用累加器:

(define (sumEvenOdd x evens odds odd?)
  (if-then-else (const? x)
                (if-then-else odd?
                              (join evens (add odds x))
                              (join (add evens x) odds))
                (if-then-else odd?
                              (sumEvenOdd (tail x) evens (add (head x) odds) (negate odd?))
                              (sumEvenOdd (tail x) (add (head x) evens) odds (negate odd?)))))


(define (sumAtEvenAndOdd xs)
  (sumEvenOdd xs 0 0 (bool #t)))

【讨论】:

    【解决方案2】:

    所以join 就像一对join-e2 可能是join?。要遍历它,您可以像使用带点列表的 pair? 一样执行相同的操作,因为您示例中的正确列表以 const 结尾。

    (let loop ((lst '(1 2 3 4 5 6 . 7)) (o 0) (e 0) (odd? #t))
      (let* ((ele (if (pair? lst) (car lst) lst))
             (no  (if odd? (+ ele o) o))
             (ne  (if odd? e (+ ele e))))
        (if (pair? lst)
            (loop (cdr lst) no ne (not odd?))
            (cons no ne))))
    

    【讨论】:

      【解决方案3】:

      这是一个简单的递归解决方案。

      (define (sum-even/odd xs)
        (if (null? xs)
            (values 0 0)
            (call-with-values
             (λ ()    (sum-even/odd (cdr xs)))
             (λ (e o) (values (+ (car xs) o) e)))))
      
      > (sum-even/odd '(1 2 3 4 5 6 7))
      16
      12
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-05-12
        • 2018-09-25
        • 2011-07-02
        • 1970-01-01
        • 2015-11-26
        • 2015-06-06
        • 1970-01-01
        相关资源
        最近更新 更多