问题始于r-help中的一个问题(下面的R代码也来自邮件列表中其他人对该问题的回答):

已知向量:

r
1x <- 1:5

如何生成如下的k列数据(k=3):

text
11 5 4
22 1 5
33 2 1
44 3 2
55 4 3

似乎不难,也有很多方法可以解决,最直接的就是用个循环,一列一列地生成并追加上去。如果需要写得简洁,可以用上apply之类的语句,如象:

r
1> sapply(1:3, function(z) { ((x - z) %% 5) +1 } )
2     [,1] [,2] [,3]
3[1,]    1    5    4
4[2,]    2    1    5
5[3,]    3    2    1
6[4,]    4    3    2
7[5,]    5    4    3

可这算不算最简洁高效的方式呢?很快邮件列表中就给出了否定的回答(群众的智慧的确是无限的,尤其在高手云集的地方)。

其实,如果能够补足四行,则可以看到一个明显的规律:

text
11   5   4
22   1   5
33   2   1
44   3   2
55   4   3
6(1) (5) (4)
7(2) (1) (5)
8(3) (2) (1)
9(4) (3) (2)

原来按列一个个数下来,正是“1, 2, 3, 4, 5”的反复重复。这时,利用matrix()函数一下就搞定了:

r
1> k <- 3
2> matrix(x, 9, k)[1:5, ]
3     [,1] [,2] [,3]
4     [1,]    1    5    4
5     [2,]    2    1    5
6     [3,]    3    2    1
7     [4,]    4    3    2
8     [5,]    5    4    3

问题的关键,还是在于一叶障目的情况下,怎么一下子看出如何补足。这让我想起中学时候的许多几何证明题,往往在添加一两条神奇的辅助线后,一切都变得那么清晰;而在不知道如何添加辅助线之前,想破脑袋都没辙。另外,著名的分马问题(老人给三个儿子分配11匹马的遗产,分别给1/2、1/4、1/6)也是用了类似的补足法(邻居借了一匹马给他们一起分配,而分配结束后又能剩下邻居的那匹马)。

看来数学还是需要天赋和灵感的,像我这么笨拙的人,只好多多练习了。