您的位置:首页 > 其它

对嵌套映射的理解

2013-08-25 14:13 267 查看
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))
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  lisp SICP