Maps 方案中的可变函数(使用嵌套映射)

Maps 方案中的可变函数(使用嵌套映射),maps,scheme,Maps,Scheme,我必须在Scheme中定义一个可变函数,其形式如下:(定义(n-loop过程[a list of pairs(x,y)]),其中pairs的列表可以是任意长度 每对指定一个下限(包括)和上限(排除)。即,以下函数调用:(n-loop(lambda(xy)(inspect(list xy)))(02)(03))生成: (list x y) is (0 0) (list x y) is (0 1) (list x y) is (0 2) (list x y) is (1 0) (list x y)

我必须在Scheme中定义一个可变函数,其形式如下:
(定义(n-loop过程[a list of pairs(x,y)])
,其中pairs的列表可以是任意长度

每对指定一个下限(包括)和上限(排除)。即,以下函数调用:
(n-loop(lambda(xy)(inspect(list xy)))(02)(03))
生成:

(list x y) is (0 0)
(list x y) is (0 1)
(list x y) is (0 2)
(list x y) is (1 0)
(list x y) is (1 1)
(list x y) is (1 2)
现在,我已经在上一次发布了关于这个主题的文章,并且得到了很好的帮助。但是,我得到了新的指导方针来坚持。解决方案只能使用嵌套地图

我的方法如下:查找第一组边界指定的所有值(在示例中为
(0 1 2)
)。这可以通过一个名为
(enumerate lowBound highBound)
的函数来完成。然后,我需要获取这些数字中的每一个,并在下一组边界
(0 1 2 3)中对每一个数字进行con运算
,导致
((0 0)(0 1)(0 2)(0 3)(1 0)…)

关于这一点,我写了以下内容:

(define (n-loop op . pairs)
     (apply op (generate pairs))
)

(define (generate pairs)
    (map (lambda (x) (cons x (generate (cdr pairs)))) 
         (map (lambda (x) (enumerate (car x) (cadr x))) pairs))
)

但是对于给定的数字,当我需要
((0 0)(0 1)(0 2)(0 3)(1 0)…)时,这会输出
(0 1 0 1 2 0 1 2 0 1 2)
。这是一个棘手的问题。有人有什么见解吗?

这个问题比你似乎意识到的要复杂得多。特别是,生成任意范围列表的笛卡尔乘积需要做更多的工作-你有没有用两个以上的范围尝试过你的过程?这激起了我的兴趣,这次我将尝试一个完整的s解决方案,仅使用为解决方案定义的过程,对列表(
cons
car
cdr
append
),
lambda
应用
map
)进行简单操作

首先,帮助程序从最简单到最难。我们需要一种生成一系列数字的方法。如果可用,请使用
构建列表
获取列表
,但如果需要从头开始实施:

(define (enumerate low high)
  (if (>= low high)
      '()
      (cons low
            (enumerate (add1 low) high))))
现在,我们需要一种机制来折叠(减少、累积)列表中的值。如果可用,请使用
foldr
,否则请按如下方式实现:

(define (reduce proc lst init)
  (if (null? lst)
      init
      (proc (car lst)
            (reduce proc (cdr lst) init))))
(n-loop (lambda (x y z) (list x y z))
        '(0 2) '(0 3) '(4 6))

> '((0 0 4) (0 0 5) (0 1 4) (0 1 5) (0 2 4) (0 2 5)
    (1 0 4) (1 0 5) (1 1 4) (1 1 5) (1 2 4) (1 2 5))
为避免列表中不必要的嵌套,请使用
flatmap
——这是一个映射和展平值列表的过程:

(define (flatmap proc lst)
  (reduce (lambda (e acc)
            (append (proc e) acc))
          lst '()))
(define (n-loop op . pairs)
  (map (lambda (tuple) (apply op tuple))
       (apply product
              (map (lambda (pair)
                     (enumerate (car pair) (cadr pair)))
                   pairs))))
这是解决方案的核心-一个生成任意长的表示范围的值列表的笛卡尔乘积的过程:

(define (product . args)
  (reduce (lambda (pool result)
            (flatmap (lambda (x)
                       (map (lambda (y)
                              (cons x y))
                            result))
                     pool))
          args
          '(())))
最后是问题中的过程。它使用上面定义的帮助程序,注意到接收到的
op
可以有任意数量的参数(取决于指定的范围数量),因此我们需要对每个生成的值元组使用
apply

(define (flatmap proc lst)
  (reduce (lambda (e acc)
            (append (proc e) acc))
          lst '()))
(define (n-loop op . pairs)
  (map (lambda (tuple) (apply op tuple))
       (apply product
              (map (lambda (pair)
                     (enumerate (car pair) (cadr pair)))
                   pairs))))
像这样测试它:

(define (reduce proc lst init)
  (if (null? lst)
      init
      (proc (car lst)
            (reduce proc (cdr lst) init))))
(n-loop (lambda (x y z) (list x y z))
        '(0 2) '(0 3) '(4 6))

> '((0 0 4) (0 0 5) (0 1 4) (0 1 5) (0 2 4) (0 2 5)
    (1 0 4) (1 0 5) (1 1 4) (1 1 5) (1 2 4) (1 2 5))

这个问题比你想象的要复杂得多。特别是,生成任意范围列表的笛卡尔积需要更多的工作-你是否尝试过使用两个以上范围的过程?这引起了我的兴趣,这次我将尝试一个完整的解决方案,只使用为解决方案定义的过程,简单操作清单上的配给(
cons
car
cdr
append
),
lambda
apply
map

首先,帮助程序从最简单到最难。我们需要一种生成一系列数字的方法。如果可用,请使用
构建列表
获取列表
,但如果需要从头开始实施:

(define (enumerate low high)
  (if (>= low high)
      '()
      (cons low
            (enumerate (add1 low) high))))
现在,我们需要一种机制来折叠(减少、累积)列表中的值。如果可用,请使用
foldr
,否则请按如下方式实现:

(define (reduce proc lst init)
  (if (null? lst)
      init
      (proc (car lst)
            (reduce proc (cdr lst) init))))
(n-loop (lambda (x y z) (list x y z))
        '(0 2) '(0 3) '(4 6))

> '((0 0 4) (0 0 5) (0 1 4) (0 1 5) (0 2 4) (0 2 5)
    (1 0 4) (1 0 5) (1 1 4) (1 1 5) (1 2 4) (1 2 5))
为避免列表中不必要的嵌套,请使用
flatmap
——这是一个映射和展平值列表的过程:

(define (flatmap proc lst)
  (reduce (lambda (e acc)
            (append (proc e) acc))
          lst '()))
(define (n-loop op . pairs)
  (map (lambda (tuple) (apply op tuple))
       (apply product
              (map (lambda (pair)
                     (enumerate (car pair) (cadr pair)))
                   pairs))))
这是解决方案的核心-一个生成任意长的表示范围的值列表的笛卡尔乘积的过程:

(define (product . args)
  (reduce (lambda (pool result)
            (flatmap (lambda (x)
                       (map (lambda (y)
                              (cons x y))
                            result))
                     pool))
          args
          '(())))
最后是问题中的过程。它使用上面定义的帮助程序,注意到接收到的
op
可以有任意数量的参数(取决于指定的范围数量),因此我们需要对每个生成的值元组使用
apply

(define (flatmap proc lst)
  (reduce (lambda (e acc)
            (append (proc e) acc))
          lst '()))
(define (n-loop op . pairs)
  (map (lambda (tuple) (apply op tuple))
       (apply product
              (map (lambda (pair)
                     (enumerate (car pair) (cadr pair)))
                   pairs))))
像这样测试它:

(define (reduce proc lst init)
  (if (null? lst)
      init
      (proc (car lst)
            (reduce proc (cdr lst) init))))
(n-loop (lambda (x y z) (list x y z))
        '(0 2) '(0 3) '(4 6))

> '((0 0 4) (0 0 5) (0 1 4) (0 1 5) (0 2 4) (0 2 5)
    (1 0 4) (1 0 5) (1 1 4) (1 1 5) (1 2 4) (1 2 5))

对。我已经定义了enumerate、Accumerate和flatmap。只是想不出如何将它们组合在一起。我将对此进行测试,谢谢。如果它对您有效,请不要忘记通过单击其左侧的复选标记来接受此答案。它还没有起作用,或者我会起作用。可能只是我的转录错误,但它保持不变ps返回列表为空。你测试过了吗?当然!我答案中的最后一行是由程序生成的。请将整个内容复制粘贴到单独的窗口中,然后重试,可能与你的代码不同。我在Racket中测试了代码-尽管我没有使用非标准过程,它应该可以在y Scheme解释器。对。我已经定义了enumerate、Accumerate和flatmap。只是想不出如何将它们组合在一起。我将对此进行测试,谢谢。如果它对您有效,请不要忘记通过单击其左侧的复选标记来接受此答案。它还没有起作用,否则我会有。可能只是转录错误对我来说,但它总是返回空列表。你测试过了吗?当然!我答案中的最后几行是由程序生成的。请将整个内容复制粘贴到单独的窗口中,然后重试,可能与你的代码不同。我在Racket中测试了代码-尽管我没有使用非标准的过程和方法它应该适用于任何方案解释器。