Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/amazon-web-services/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scheme 如何以非平凡的方式组合两个生成器_Scheme_Puzzle_Generator - Fatal编程技术网

Scheme 如何以非平凡的方式组合两个生成器

Scheme 如何以非平凡的方式组合两个生成器,scheme,puzzle,generator,Scheme,Puzzle,Generator,我有一个生成器,它生成2的幂的所有正整数,还有一个生成器生成3的幂的所有整数。我现在需要用这些来生成形式为2^I*3^j的整数,其中I,j>=0,0,以递增的顺序 我认为,使用生成器的目的是减少内存消耗。我已经试着这样做了一段时间,但没有结果。请提供帮助。至少如果我理解您的问题,您只需要合并两个生成器的结果: 从每个生成器生成一个输出 生成两者中较小的一个作为下一个输出 从该生成器生成下一个输出 返回步骤2 如果两个生成器生成相等的值,则生成该值作为输出,并从每个生成器生成下一个值 请注意,尽管

我有一个生成器,它生成2的幂的所有正整数,还有一个生成器生成3的幂的所有整数。我现在需要用这些来生成形式为2^I*3^j的整数,其中I,j>=0,0,以递增的顺序


我认为,使用生成器的目的是减少内存消耗。我已经试着这样做了一段时间,但没有结果。请提供帮助。

至少如果我理解您的问题,您只需要合并两个生成器的结果:

  • 从每个生成器生成一个输出
  • 生成两者中较小的一个作为下一个输出
  • 从该生成器生成下一个输出
  • 返回步骤2
  • 如果两个生成器生成相等的值,则生成该值作为输出,并从每个生成器生成下一个值

    请注意,尽管它通常用于对现有数据进行排序,而不是生成新数据,但这与普通合并排序中使用的合并类似,只是我假设您不需要重复项,而合并排序通常会保留重复项

    编辑:多亏了lpthnc,我重读了这个问题,我认为他是对的——我误读了原来的问题。要获得正确的输出,您需要创建第三个生成器并生成(在本例中)6的倍数,并在该结果集和其他两个生成器的结果集之间使用三向合并


    我没怎么玩过它,但我相信在最近的PLT方案迭代中的惰性语言级别(或惰性模块)将允许您编写代码来生成整个无限序列,理论上这将使用无限的时间和内存,但只根据需要计算其中的有限子集。

    没有任何示例的简单解决方案正在创建一个新的解决方案

    for (i = 0; i < X; i++)
    {
     if (i%2 or i%3)
     {
      cout << i
     }
    }
    
    (i=0;i { 如果(i%2或i%3) {
    只需将两个有序列表合并一个la即可


    摘自。

    编辑。我看得越多,就越觉得自己搞错了——其他人似乎已经有了更好的答案

    抱歉,这些都不在scheme中,只是伪代码

    以下代码与我从您的问题中获得的思考过程相匹配:

    编辑:修改了伪代码,现在我意识到它是“2^I*3^j”,而不是“2^I,3^j”

    //如果我靠近了,这次, //输入min-i=0,max-i=2,min-j=0,max-j=2 //应该得到像这样的输出 // 2^0 * 3^0 = 1 // 2^0 * 3^1 = 3 // 2^0 * 3^2 = 6 // 2^1 * 3^0 = 2 // 2^1 * 3^1 = 6 // 2^1 * 3^2 = 12 // 2^2 * 3^0 = 4 // 2^2 * 3^1 = 12 // 2^2 * 3^2 = 24 输入min-i、max-i、min-j、max-j 让当前值=1 对于i=最小-i到最大-i 对于j=最小-j到最大-j DO 打印“2^”.i.*j^.j.=”当前值 当前值*=3; 完成//结束j循环 当前值*=2 完成//结束i循环

    这在Haskell中非常简单:

    merge as bs =
      case (as, bs) of
        ([], _) -> bs
        (_, []) -> as
        ((a:as'), (b:bs')) ->
          if a <= b
            then a : (merge as' bs)
            else b : (merge as bs')
    rmDups as =
      case as of
        [] -> []
        [a] -> [a]
        (a:bs@(b:_)) ->
          if a == b
            then rmDups bs
            else a:(rmDups bs)
    take 25 $ rmDups $ merge (map (2^) [1..]) (map (3^) [1..])
    

    虽然我想有一种更优雅的方式来做…

    我对发电机不太了解, 但是,我可以提出一个基于流的解决方案(延迟构造, 可能是无限列表),它们有些相似

    我的方法是创建一个流 其“状态”本身就是一股溪流

    个体内部的数字流, 让我们称之为三流, 将代表3的连续幂的列表,从1开始, 乘以给定的二次幂。 然后我们可以集合无限多这样的三条流, 从1开始,每连续2次方一次。 让我们称之为2流

    ascii技术中的初始状态为:

    ---------------------- --- -- -
    | The 2-stream ...
    --|----|----|----|---- --- -- -
      V    V    V    V
     |1| | 2| | 4| | 8|
     |3| | 6| |12| |24| ...
     |9| |18| |36| |72|         The 3-streams
      :    :    :    :
    
    现在,我们要操纵它,以便在任何时候, 3流将在2流中排序 关于它们的第一个元素。 因此,生成的下一个最小数 将始终是第一个3流的第一个元素

    因此,要获得您希望获得的序列中的下一个数字, 我们要拿出第一条三流, 拉出它的第一个元素(我们感兴趣的数字), 然后在2流中重新插入3流 位于由其新的第一个元素确定的位置。 提取第一个数字(1)后的新状态为:

    ---------------------- --- -- -
    | The 2-stream ...
    ---|----|----|----|---- --- -- -
       V    V    V    V
     | 2| | 3| | 4| | 8|
     | 6| | 9| |12| |24| ...
     |18| |27| |36| |72|         The 3-streams
      :    :    :    :
    
    请注意,此方法并不具体依赖于2^i、3^j或乘法 (就在2^i*3^j随i和j单调增加时)。 我已经发布了另一个答案,而且 其结果是更加简单和快速。 别相信我,这和数学无关

    下面是一个使用流的示例实现:

    用生成器实现这一点我想是可以做到的, 但棘手的部分是实现
    (insert)
    。 你可以通过组合生成器来实现, 但每次拉取一个数字时,都会增加一个“层”, 而使用
    (insert)
    创建的流与原始流共享其尾部 (层最终合并)。

    使用自读流 您可以使用自读流解决此问题:

       -----------        -----------
       |  pow 2  |------->|         |
       -----------        |         |
                          |  merge  |-------+------------>
       -----------        |         |       |
    .->|   x 3   |------->|         |       |
    |  -----------        -----------       |
    \_______________________________________/
    
    第一股水流产生两股力量, 而第二个则确保生成的所有数字 乘以3并重新输入到输出中。 merge操作符确保对输出进行排序

    请注意,我们必须使用1“种子”输出流, 或者,第一个元素在求值时将尝试生成自己

    代码如下:

    (require srfi/41)
    
    (define (merge s1 s2)
      (stream-match s1 ((x . xs)
        (stream-match s2 ((y . ys)
          (if (< x y)
            (stream-cons x (merge xs s2))
            (stream-cons y (merge ys s1))))))))
    
    (define (the-stream)
      (letrec ((s
        (stream-cons 1 (merge (stream-map     (lambda (x) (* 3 x)) s)
                              (stream-iterate (lambda (x) (* 2 x)) 2)))))
      s))
    
    使用生成器和队列 我们也可以用python的生成器来实现, 但我们需要使用队列来存储反馈循环中等待的数字:

    # Merge the output of two generators
    def merge(g1, g2):
        v1 = g1.next()
        v2 = g2.next()
        while 1:
            if v1 < v2:
                yield v1
                v1 = g1.next()
            else:
                yield v2
                v2 = g2.next()
    
    # Generates the powers of 2, starting with n
    def pow2(n):
        while 1: yield n; n *= 2
    
    # Generates values shifted from the given 'q' and multiplied by 3
    def mul3(q):
        while 1: yield q.pop(0) * 3
    
    # The generator we want
    def pow23():
        q = []
        v = 1
        g = merge(pow2(2), mul3(q))
        while 1:
            yield v
            q.append(v)
            v = g.next()
    
    g23 = pow23()
    for i in range(10000): g23.next()
    print g23.next()
    
    为了有价值,我做了一个方案实施 (使用闭合器作为生成器)
    这显示了大致相同的性能。

    @Greg,你的发型很漂亮!你想要的东西能以2或3的倍数递增的顺序找到所有东西吗?我不知道你在找什么。你在解析什么东西吗?还是像2,3,4,6,8,9这样的直接计数器。对不起,2或3的幂递增的顺序。每次我调用它,我
    ---------------------- --- -- -
    | The 2-stream ...
    ---|----|----|----|---- --- -- -
       V    V    V    V
     | 2| | 3| | 4| | 8|
     | 6| | 9| |12| |24| ...
     |18| |27| |36| |72|         The 3-streams
      :    :    :    :
    
    (require srfi/41)
    
    ; Geometric sequence with initial value 'init', and ratio 'r'
    (define (make-geoseq init r)
      (stream-cons
        init
        (make-geoseq (* r init) r)))
    
    ; Your power generators
    (define pow2 (make-geoseq 1 2))
    (define pow3 (make-geoseq 1 3))
    
    ; Construct a 3-stream from the pow3 sequence
    (define (make-3stream mult)
      (stream-map (lambda (x) (* mult x)) pow3))
    
    ; Construct the (initial) 2-stream from the pow2 sequence
    (define initial-2stream
      (stream-map make-3stream pow2))
    
    ; Insert a modified 3-stream into the given 2-stream, at the right position
    (define (insert two-stream three-stream)
      (if (< (stream-car three-stream)
             (stream-car (stream-car two-stream)))
        ; we have the smallest 3-stream, put it at the front
        (stream-cons
          three-stream
          two-stream) 
        ; otherwise, recurse
        (stream-cons
          (stream-car two-stream)
          (insert (stream-cdr two-stream) three-stream))))
    
    ; Construct a 2^n * 3^p stream with the given 2-stream as its "state"
    (define (make-the-stream current-2stream)
      (let*
        ; pull out the first 3-stream
        ((first-3s (stream-car current-2stream))
         (other-3s (stream-cdr current-2stream))
         ; use its first element as our next value
         (next-val (stream-car first-3s))
         ; reinsert its tail into the 2-stream's tail
         (next-2s (insert other-3s (stream-cdr first-3s))))
    
        ; and use the resulting 2-stream to construct the (outer) stream's tail
        (stream-cons
          next-val
          (make-the-stream next-2s))))
    
    ; Now, we can construct the stream we want
    (define the-stream (make-the-stream initial-2stream))
    
    $ mzscheme -f pow23.scm -e '(display (stream->list (stream-take 20 the-stream)))'
    (1 2 3 4 6 8 9 12 16 18 24 27 32 36 48 54 64 72 81 96)
    
    $ time mzscheme -f pow23.scm -e '(display (stream-ref the-stream 10000))'
    161968247347450370721577384417107686788864605658546176
    real    0m12.550s
    user    0m11.005s
    sys     0m0.340s
    
       -----------        -----------
       |  pow 2  |------->|         |
       -----------        |         |
                          |  merge  |-------+------------>
       -----------        |         |       |
    .->|   x 3   |------->|         |       |
    |  -----------        -----------       |
    \_______________________________________/
    
    (require srfi/41)
    
    (define (merge s1 s2)
      (stream-match s1 ((x . xs)
        (stream-match s2 ((y . ys)
          (if (< x y)
            (stream-cons x (merge xs s2))
            (stream-cons y (merge ys s1))))))))
    
    (define (the-stream)
      (letrec ((s
        (stream-cons 1 (merge (stream-map     (lambda (x) (* 3 x)) s)
                              (stream-iterate (lambda (x) (* 2 x)) 2)))))
      s))
    
    $ mzscheme -f feedback.scm -e '(display (stream->list (stream-take 20 (the-stream))))'
    (1 2 3 4 6 8 9 12 16 18 24 27 32 36 48 54 64 72 81 96)
    
    $ time mzscheme -f feedback.scm -e '(display (stream-ref (the-stream) 10000))'
    161968247347450370721577384417107686788864605658546176
    real    0m1.746s
    user    0m1.344s
    sys     0m0.156s
    
    # Merge the output of two generators
    def merge(g1, g2):
        v1 = g1.next()
        v2 = g2.next()
        while 1:
            if v1 < v2:
                yield v1
                v1 = g1.next()
            else:
                yield v2
                v2 = g2.next()
    
    # Generates the powers of 2, starting with n
    def pow2(n):
        while 1: yield n; n *= 2
    
    # Generates values shifted from the given 'q' and multiplied by 3
    def mul3(q):
        while 1: yield q.pop(0) * 3
    
    # The generator we want
    def pow23():
        q = []
        v = 1
        g = merge(pow2(2), mul3(q))
        while 1:
            yield v
            q.append(v)
            v = g.next()
    
    g23 = pow23()
    for i in range(10000): g23.next()
    print g23.next()
    
    $ time python feedback.py 
    161968247347450370721577384417107686788864605658546176
    real    0m0.150s
    user    0m0.112s
    sys     0m0.012s