|
|
本帖最后由 不点 于 2022-9-13 07:53 编辑
现在给出五兵位置与整体编号互映射的两个函数,都已经过调试验证。
在两个函数之后的结尾处,附有简短的测试代码。
- <!DOCTYPE html>
- <html>
- <head> <meta charset="UTF-8">
- <script>
- //现在给出已知整体编号 SN 求五兵位置的函数
- //每个兵的位置有 55 种可能性,这 55 个位置的编号为 0~54。
- function get_五兵位置_from_整体编号 (SN) {
- var A, B, C, D, E, t, m;
- if (SN == 0) {
- return [null, null, null, null, null]; // 五个兵都不存在
- }
- if (SN < 56) { // 56 = 1 + 55
- return [SN - 1, null, null, null, null]; // 只存在一个兵
- }
- if (SN < 1541) { // 1+55+55*54/2
- //只存在两个兵
- A = SN - 55; // 当前元素在当前层内部的编号, 从 1 开始
- // 计算当前元素在当前层中的行号 B
- t = 2 * A;
- B = Math.ceil(Math.sqrt(t) - 0.5);
- // 用 B 计算前一行最大元素在当前层内部的编号 m
- m = B * (B - 1) / 2;
- A -= m; // 当前元素在当前行内部的编号,从 1 开始
- return [A-1, B, null, null, null]; // 双兵的位置
- }
- if (SN < 27776) { // 1+55+55*54/2+55*54*53/6
- //只存在三个兵
- A = SN - 1540; // 当前元素在当前(三维)锥内部的编号, 从 1 开始
- // 计算当前元素在当前(三维)锥中的层号 C
- t = 6 * A;
- C = Math.ceil((t + t**(1/3))**(1/3) - 1);
- // 用 C 计算上一层最大元素在当前(三维)锥内部的编号 m
- m = (C + 1) * C * (C - 1) / 6;
- A -= m; // 当前元素在当前层内部的编号,从 1 开始
- // 计算当前元素在当前层中的行号 B
- t = 2 * A;
- B = Math.ceil(Math.sqrt(t) - 0.5);
- // 用 B 计算前一行最大元素在当前层内部的编号 m
- m = B * (B - 1) / 2;
- A -= m; // 当前元素在当前行内部的编号,从 1 开始
- return [A-1, B, C+1, null, null]; // 三个兵的位置
- }
- if (SN < 368831) { // 1+55+55*54/2+55*54*53/6+55*54*53*52/24
- //只存在四个兵
- A = SN - 27775; // 当前元素在四维超锥内部的编号, 从 1 开始
- // 计算当前元素所在(三维)锥号 D
- t = 24 * A;
- D = Math.ceil ( -1.5 + Math.sqrt(1.25 + Math.sqrt(t)) );
- // 用 D 计算上一锥最大元素在四维超锥内部的编号 m
- m = (D + 2) *(D + 1) * D * (D - 1) / 24;
- A -= m; // 当前元素在当前(三维)锥内部的编号,从 1 开始
- // 计算当前元素在当前(三维)锥中的层号 C
- t = 6 * A;
- C = Math.ceil((t + t**(1/3))**(1/3) - 1);
- // 用 C 计算上一层最大元素在当前(三维)锥内部的编号 m
- m = (C + 1) * C * (C - 1) / 6;
- A -= m; // 当前元素在当前层内部的编号,从 1 开始
- // 计算当前元素在当前层中的行号 B
- t = 2 * A;
- B = Math.ceil(Math.sqrt(t) - 0.5);
- // 用 B 计算前一行最大元素在当前层内部的编号 m
- m = B * (B - 1) / 2;
- A -= m; // 当前元素在当前行内部的编号,从 1 开始
- return [A-1, B, C+1, D+2, null]; // 四个兵的位置
- }
- //五个兵都在
- A = SN - 368830; // 当前元素在五维超锥内部的编号, 从 1 开始
- // 用 A 计算当前元素所在(四维)超锥号 E
- t = 120 * A;
- E = Math.ceil ( -2 + (t + 5*(t+5*t**0.6)**0.6 - 4 * t**0.2)**0.2 );
- // 用 E 计算上一(四维)超锥最大元素在五维超锥内部的编号 m
- m = (E + 3)* (E + 2) *(E + 1) * E * (E - 1) / 120;
- A -= m; // 当前元素在当前(四维)超锥内部的编号, 从 1 开始
- // 用 A 计算当前元素所在(三维)锥号 D
- t = 24 * A;
- D = Math.ceil ( -1.5 + Math.sqrt(1.25 + Math.sqrt(t)) );
- // 用 D 计算上一锥最大元素在四维超锥内部的编号 m
- m = (D + 2) *(D + 1) * D * (D - 1) / 24;
- A -= m; // 当前元素在当前(三维)锥内部的编号,从 1 开始
- // 计算当前元素在当前(三维)锥中的层号 C
- t = 6 * A;
- C = Math.ceil((t + t**(1/3))**(1/3) - 1);
- // 用 C 计算上一层最大元素在当前(三维)锥内部的编号 m
- m = (C + 1) * C * (C - 1) / 6;
- A -= m; // 当前元素在当前层内部的编号,从 1 开始
- // 计算当前元素在当前层中的行号 B
- t = 2 * A;
- B = Math.ceil(Math.sqrt(t) - 0.5);
- // 用 B 计算前一行最大元素在当前层内部的编号 m
- m = B * (B - 1) / 2;
- A -= m; // 当前元素在当前行内部的编号,从 1 开始
- return [A-1, B, C+1, D+2, E+3]; // 五个兵的位置
- }
- //下面的函数是, 已知五兵位置,算出整体编号。
- function get_整体编号_from_五兵位置 (pos) {
- var B, C, D, E, m;
- if (typeof pos[0] !== 'number') {
- return 0; // 五个兵都不存在
- }
- if (typeof pos[1] !== 'number') {
- return pos[0] + 1; // 只存在一个兵位于 pos[0]
- }
- if (typeof pos[2] !== 'number') {
- // 只存在两个兵位于 pos[0], pos[1]
- m = 1 + 55;
- B = pos[1]; // 在本层中的行号
- //前一行的最大元素在当前层中的序号
- m += B * (B - 1) / 2;
- return m + pos[0];
- }
- if (typeof pos[3] !== 'number') {
- // 只存在三个兵位于 pos[0], pos[1], pos[2]
- m = 1 + 55 + 55 * 54 / 2;
- C = pos[2] - 1; // 层号
- //前一层的最大元素在当前(三维)锥中的序号
- m += (C + 1) * C * (C - 1) / 6;
- B = pos[1]; // 在本层中的行号
- //前一行的最大元素在当前层中的序号
- m += B * (B - 1) / 2;
- return m + pos[0];
- }
- if (typeof pos[4] !== 'number') {
- // 只存在四个兵位于 pos[0], pos[1], pos[2], pos[3]
- m = 1 + 55 + 55 * 54 / 2 + 55 * 54 * 53 / 6;
- D = pos[3] - 2; // 锥号
- //前一(三维)锥中的最大元素在当前(四维)超锥中的序号
- m += (D + 2) * (D + 1) * D * (D - 1) / 24;
- C = pos[2] - 1; // 层号
- //前一层的最大元素在当前(三维)锥中的序号
- m += (C + 1) * C * (C - 1) / 6;
- B = pos[1]; // 在本层中的行号
- //前一行的最大元素在当前层中的序号
- m += B * (B - 1) / 2;
- return m + pos[0];
- }
- // 五个兵都在
- m = 1 + 55 + 55 * 54 / 2 + 55 * 54 * 53 / 6 + 55 * 54 * 53 * 52 / 24;
- E = pos[4] - 3; // 超锥号
- //前一(四维)超锥中的最大元素在当前五维超锥中的序号
- m += (E + 3) * (E + 2) * (E + 1) * E * (E - 1) / 120;
- D = pos[3] - 2; // 锥号
- //前一(三维)锥中的最大元素在当前(四维)超锥中的序号
- m += (D + 2) * (D + 1) * D * (D - 1) / 24;
- C = pos[2] - 1; // 层号
- //前一层的最大元素在当前(三维)锥中的序号
- m += (C + 1) * C * (C - 1) / 6;
- B = pos[1]; // 在本层中的行号
- //前一行的最大元素在当前层中的序号
- m += B * (B - 1) / 2;
- return m + pos[0];
- }
- // 以下是测试代码
- for (var i = 0; i < 3847592; i++) {
- var pos = get_五兵位置_from_整体编号 (i);
- var n = get_整体编号_from_五兵位置 (pos);
- if (n != i) {
- console.log('出错! ' + i + ' ==== ' + pos + ' ==== ' + n);
- } else
- if ((i & 4095) == 0) {
- console.log('------ ' + i + ' ==== ' + pos + ' ==== ' + n);
- }
- //if (i > 30000) break;
- }
- console.log('--OK-- ' + '--last--' + ' ==== ' + pos + ' ==== ' + n);
- </script>
- </head>
- <body>
- </body>
- </html>
复制代码 |
|