【问题标题】:Generating a stream of all possible tuples from given streams using Scheme使用 Scheme 从给定的流中生成所有可能的元组的流
【发布时间】:2020-11-13 10:54:42
【问题描述】:

我正在尝试编写一个过程stream-weighted-tuples,它采用权重过程和任意数量的流来生成元组流。 例如,

(stream-weighted-tuples
  (lambda (t) (+ (car t) (cadr t) (caddr t))
  integers
  integers
  integers)

应该生成(1 1 1) (1 1 2) (1 2 1) (2 1 1) (1 1 3) (1 2 2) (1 3 1) (2 1 2) (2 2 1) (3 1 1) (1 1 4) (1 2 3) ...的流。

我受到 SICP 中的exercise 3.70 的启发,它是关于编写一个过程weighted-pairs,它采用两个流和一个权重过程来根据权重按顺序生成一对流。 所以基本上,这是对weighted-pairs 过程的概括,可以采用两个以上的流。

我写了以下版本:

    (define (stream-weighted-tuples weight . streams)
      (cond ((null? streams)
             (error "No streams given -- STREM-WEIGHTED-TUPLES"))
            ((null? (cdr streams))
             (stream-map list (car streams)))
            (else
              (let ((s (car streams))
                    (rest (cdr streams)))
                (if (stream-null? s)
                    the-empty-stream  ; {} x S = {}
                    (stream-merge-weighted
                      weight
                      (stream-map (lambda (tuple)
                                    (cons (stream-car s) tuple))
                                  (apply stream-weighted-tuples
                                         (lambda (tuple)  ; partial weight
                                           (weight (cons (stream-car s)
                                                         tuple)))
                                         rest))
                      (apply stream-weighted-tuples
                             weight
                             (stream-cdr s)
                             rest)))))))

(这显然不起作用)。 这个想法是合并 1. 由consing 第一个流的第一个元素产生的流与由 其余元组组成的(递归构造的)流的每个元素给定流的数量,以及 2. 由第一个流的stream-cdr 的元组和其余给定流的元组组成的流。

这不起作用,因为在无限流的情况下生成流 2 不会停止(与 exercise 3.68 中的 pairs 过程不工作的原因相同)。

这是我实现的stream-merge-weighted

    (define (stream-merge-weighted weight s1 s2)
      (cond ((stream-null? s1) s2)
            ((stream-null? s2) s1)
            (else
              (let* ((s1car (stream-car s1))
                     (s2car (stream-car s2))
                     (s1car-weight (weight s1car))
                     (s2car-weight (weight s2car)))
                (cond ((<= s1car-weight s2car-weight)
                       (cons-stream
                         s1car
                         (stream-merge-weighted weight
                                                (stream-cdr s1)
                                                s2)))
                      ((> s1car-weight s2car-weight)
                       (cons-stream
                         s2car
                         (stream-merge-weighted weight
                                                s1
                                                (stream-cdr s2)))))))))

有没有办法递归构造这个问题?


编辑:我在这个问题中所说的“元组”实际上是一个语义上表示元组的方案列表。

作为参考,我保留了流原语的实现(与 SICP 中的实现相同):

    (define-syntax cons-stream
      (syntax-rules ()
        ((_ a b)
         (cons a (delay b)))))

    (define (stream-car stream)
      (car stream))
    (define (stream-cdr stream)
      (force (cdr stream)))

    (define (stream-null? stream)
      (null? stream))
    (define the-empty-stream '())

    (define (stream-map proc s)
      (if (stream-null? s)
          the-empty-stream
          (cons-stream
            (proc (stream-car s))
            (stream-map proc (stream-cdr s)))))

【问题讨论】:

    标签: recursion stream scheme sicp lazy-sequences


    【解决方案1】:

    我设法使用类似于the pairs procedure shown in SICP 的递归结构来解决它。

    下面的stream-weighted-tuples 使用流的cdr 的递归构造的元组流(rest-tuples),然后使用相同的递归策略“配对”(与原始的pair 过程不同,另一个流已经是一个元组流)它与流的carcombine-with-rest)。

        (define (stream-weighted-tuples weight . streams)
          (if (null? streams)
              (cons-stream '() the-empty-stream)
              (let* ((stream (car streams))
                     (rest (cdr streams))
                     (rest-tuples
                       (apply stream-weighted-tuples
                              (lambda (tuple)  ; partial weight
                                (weight (cons (stream-car stream) tuple)))
                              rest)))
                (let combine-with-rest ((stream stream)
                                        (rest-tuples rest-tuples))
                  (if (or (stream-null? stream)
                          (stream-null? rest-tuples))
                      the-empty-stream  ; {} x S = {}
                      (let ((s-car (stream-car stream))
                            (s-cdr (stream-cdr stream))
                            (r-car (stream-car rest-tuples))
                            (r-cdr (stream-cdr rest-tuples)))
                        (cons-stream (cons s-car r-car)
                                     (stream-merge-weighted
                                       weight
                                       (stream-map (lambda (t) (cons s-car t))
                                                   r-cdr)
                                       (stream-merge-weighted
                                         weight
                                         (stream-map (lambda (x) (cons x r-car))
                                                     s-cdr)
                                         (combine-with-rest s-cdr r-cdr))))))))))
    

    注意,weight 过程要求元组的cdr 独立于cars 进行排序,即仅 W(a, b, c) >= W(x, y, z)如果 W(b, c) >= W(y, z)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-23
      • 1970-01-01
      • 2023-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多