需求概况
这个需求有实际的应用场景,就是教室中座位的分组。这个分组可以用于考试时的座位分配,增加满足不同组考生不能相邻的业务规则。
情况是这样的,有一个教室,其中有MxN个座位。它们的编号,就是从1编到MxN。编号规则就是按行从左到右依次编号,如一个6x5和5x6的座位布局,编号方式分别如下:
js
01 02 03 04 05
06 07 08 09 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
26 27 28 29 30
01 02 03 04 05 06
07 08 09 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24
25 26 27 28 29 30
现在的需求就是,将教室中的座位,分为两组,使在同一组中的任意两个座位,都不会相邻,相邻的定义,就是前后左右直接相连。显然这也会导致数组中元素的数量也基本相等(平均分成两组)。这个计算方法的输入就是M(行数)和N(列数);输出是两个数组,数组中的元素就是座位的编号。
实现
如果我们认真观察座位编号的布局,就会发现,最简单的方式,就是"画斜线"来分组,相邻斜线上的两组元素,肯定不相邻。按照这个基本构思,编写的示例和测试代码如下:
js
const g1 = (x,y)=>{
let i,
ilast = x * y,
igroup = [[],[]];
for (i=1;i<=ilast;i++) {
if (y % 2) {
igroup[i%2 ? 0 : 1].push(i);
} else if ((0 | (i-1) / y) % 2) {
igroup[(i+1) % 2 ? 0 : 1].push(i);
} else {
igroup[i % 2 ? 0 : 1].push(i);
};
};
return igroup;
};
let
g = g1(5,6);
console.log(g[0].join(),"\n",g[1].join());
g = g1(6,5);
console.log(g[0].join(),"\n",g[1].join());
简单分析一下:
首先将座位布局分为两大类,列数为奇数和列数为偶数的。
对于列数为奇数的情况,非常简单,就是所有奇数编号为一组,偶数编号为一组。
对于列数为偶数的情况,稍微复杂一点。对于偶数行(包括第一行)的元素,处理方式就是按照列的奇偶来分组。对于奇数行的元素,将这个元素的值+1,然后按奇偶分组。
所以,最后就是遍历整个编号数组,按照这三种情况来将当前的元素,放在奇数组,或者偶数组中。最后的测试代码,我们就可以看到各种情况的计算结果。