Maps 方案中的可变函数(使用嵌套映射)
我必须在Scheme中定义一个可变函数,其形式如下: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)
(定义(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中测试了代码-尽管我没有使用非标准的过程和方法它应该适用于任何方案解释器。