对嵌套映射的理解

SICP第二章第82页,嵌套映射。


问题0:给定自然数n,找出所有不同的有序对i和j,其中1 <= j < i <= n,使得 i + j 是素数。

我们这里只考虑问题的前一部分,并记为

问题1: 给定自然数n,找出所有不同的有序对i和j,记为( i, j ),其中1 <= j < i <= n。

在问题0中,序对(i,j)和(j,i)是等价的,所以我们在问题1中也延续这个约定。


在命令式编程语言中,我们会用嵌套for循环来解决这个问题,示例代码如下:

for(int i = 1; i < n; i++){
  for(int j = 1; j < i; j++){
    print(i,j);
  }
}

这里,我们要用lisp的思路来解决这个问题。初次用lisp来思考,会很不适应,即使在看到了书中给出的的代码,也没有一个直观的理解。问题在于自己对于嵌套映射并没有一个更加深入的、直观的理解。

经过思考,对这个问题有了一个直观的理解,也具有可操作性。

核心思路:

嵌套映射,就是映射之后再映射,所以,要分成两个步骤来处理。

具体步骤(针对问题1):

第一步:找到第一次映射的目标,问题1中涉及两个变量,i和j,我们先处理i,i的取值范围是(1 2 3 ... n-1),我们另i映射到其自身,形成第一个序列;

第二步:将第一步的结果序列中的每个值(这里记为i)映射到(i,j),其中1 <= j < i。


这里关键是要形成映射的图像,然后我就发现lisp代码是多么的直观。

第一步:

将i取值范围映射到其自身,没什么可解释的。但从问题中发现这个初始序列,是最关键的。

假设n=10。

(def n 10)

(map (fn [i] (identity i)) 
     (range 1 n))

第二步:

根据具体的问题不同,这一步的具体操作也不同。在这个问题中,给定i,需要找出所有的序对(i,j),其中1 <= j < i。

从映射的角度来看,就是将i映射到序对(i,j),其中1 <= j < i。


(def i 5)

(map (fn [j] (list i j))
     (range 1 i))


现在,将上面两个步骤组合到一起。

(map (fn [i] (map (fn [j] (list i j))
                  (range 1 i))) 
     (range 1 n))


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值