【问题标题】:Racket: Stream negative and ith element problem球拍:流负和第i个元素问题
【发布时间】:2019-10-07 08:37:49
【问题描述】:

我有两个 Racket 编程作业问题:

第一个:写一个函数kth-item,它有两个参数,第一个是流s,第二个是数字k,它产生从流中提取k个元素的结果,只返回最后一个元素.与前一个非常相似,但只返回一个元素。你可以假设 k 大于 0。

第二个:写一个流 negate-2-and-5,它类似于自然数流(即 1, 2, 3, ...),除了可被 2 或 5 整除的数字被取反(即, 1, -2, 3, -4, -5, -6, 7, -8, 9, -10, 11, -12, 13, -14, ...)。请记住,流是一个 thunk,当被调用时会产生一对,其中对的 car 是下一个数字,而 cdr 将是流的延续。

对于第一个问题,我知道如何获取 ith 的列表,但我不知道如何继续获取最后一个元素。

对于第二个问题,我知道如何获得 2 或 5 个作品,但我不知道如何组合它们,因此 2 和 5 可以同时工作。

(define (next-k-items s k)
  (if (<= k 0)
      empty
      (cons (car (s))
            (next-k-items (cdr (s)) (- k 1)))))


(define (negate-2-and-5)
  (define (f x) (cons (if (= 0 (remainder x 5)) (- x) x)
                      (lambda () (f (+ x 1)))))
  (f 1))

这里是测试代码:

(check-expect (kth-item nats 3) 3)

(check-expect (next-k-items negate-2-and-5 7) '(1 -2 3 -4 -5 -6 7))

【问题讨论】:

    标签: lambda stream racket


    【解决方案1】:
    (require racket)
    

    流可以被认为是无限列表,其中 cdr 被包裹在一个 thunk(不带参数的 lambda)中

    (define-syntax-rule (cons-stream x y)
      (cons x (lambda () y)))
    

    为了更容易对流进行操作,我们定义了以下接口:

    (define stream? pair?)
    (define null-stream null)
    (define null-stream? null?)
    (define stream-first car)
    (define (stream-rest s) ((cdr s)))
    

    可以使用自引用创建流:

    (define ones (cons-stream 1 ones))
    

    我们可以在流上定义地图:

    (define (stream-map f s)
      (if (null-stream? s)
          null-stream
          (cons-stream (f (stream-first s))
                       (stream-map f (stream-rest s)))))
    
    (define (stream-map2 f s1 s2)
      (if (null-stream? s1)
          null-stream
          (cons-stream (f (stream-first s1) (stream-first s2))
                       (stream-map2 f (stream-rest s1)
                                    (stream-rest s2)))))
    

    ...并用它来制作一个 nats 流:

    (define nats (cons-stream 1 (stream-map2 + ones nats)))
    

    你想要的函数可以用上面的函数清晰地定义:

    ;; Stream Number -> Number
    ;; the kth item of s
    (define (kth-item s k)
      (if (= k 1)
          (stream-first s)
          (kth-item (stream-rest s) (sub1 k))))
    
    
    (check-expect (kth-item nats 1) 1)
    (check-expect (kth-item nats 2) 2)
    (check-expect (kth-item nats 3) 3)
    

    在您的代码中,(s) 不正确,因为 s 不是 lambda。我们需要 cons 第一个元素 (car s)force 流的其余部分 ((cdr s))。这由stream-firststream-rest 负责。

    ;; Stream Number -> Stream
    ;; builds a list of first k items of s
    (define (next-k-items s k)
      (if (= k 0)
          empty
          (cons (stream-first s)
                       (next-k-items (stream-rest s) (- k 1)))))
    
    (check-expect (next-k-items nats 10) '(1 2 3 4 5 6 7 8 9 10))
    

    map 的定义再次证明是有用的:

    ;; Stream -> Stream
    ;; negates the multiples of 2 and 5
    (define (negate-2-and-5 s)
      (stream-map (λ (x) (if (or (zero? (modulo x 2))
                                 (zero? (modulo x 5)))
                             (* -1 x)
                             x))
                  s))
    

    ...和next-k-items

    (check-expect (next-k-items (negate-2-and-5 nats) 7) '(1 -2 3 -4 -5 -6 7))
    

    【讨论】:

      猜你喜欢
      • 2017-08-07
      • 1970-01-01
      • 2013-11-22
      • 2012-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多