回复 2# CrLf
分析一下这里最核心的算法: 8进制, 同余原理 计算邻居数, 逻辑计算
设 3 X 3 方格区域如下
a,b,c,d,e,f,g,h,i 的值均为 0 或者 1, 0abcdefghi 可以构成一个 8 进制数, 换算成十进制就是
0abcdefghi = a*8^8 + b*8^7 + c*8^6 + d*8^5 + e*8^4 + f*8^3 + g*8^2 + h*8^1 + i*8^0
根据同余定理, 8^8, 8^7, ... 8^2, 8 对 7 的余数都是 1, 所以 0abcdefghi %% 7 = (a+b+c+d+e+f+g+h+i) %% 7
a+b+c+d+e+f+g+h+i 的值域为 [0,9], 这是 3 X 3 区域的总人口数, 取余数后有这样一个映射
[0,1,2,3,4,5,6,7,8,9] --> [0,1,2,3,4,5,6,0,1,2]
而如果去掉中间方格 e 时有
(0abcdefghi & 0111101111) %% 7 = (a+b+c+d+f+g+h+i) %% 7
a+b+c+d+f+g+h+i 的值域为 [0,8], 是中间方格的邻居总数, 取余数后有这样一个映射
[0,1,2,3,4,5,6,7,8] --> [0,1,2,3,4,5,6,0,1]
康威生命游戏的规则是 B3/S23, 即在空位置的邻居有 3 个时, 可以在此位置新生; 在某位置有生命 且 周围邻居是 2 或 3 个时, 此位置生命可以继续存活; 其他任何情况下, 一个位置的生命将死亡, 或者保持无生命.
这个规则还可以换成如下两种不同的描述:
A. 当某位置的邻居为 2 个时, 此位置的下一代保持当前状态; 当邻居数为 3 个时, 无论当前状态如何, 下一代一定有生命.
B. 当 3X3 区域的人口总数 < 3 个时, 下一代在中心位置一定没有生命; 当区域人口总数 = 3 个时, 下一代在中心位置一定有生命; 当区域人口总数 = 4 个时, 中心位置保持当前状态; 当人口总数 > 4 个时, 下一代在中心位置一定没有生命.
以下是 描述 A 的伪代码
set /a "n=(0abcdefghi & 0111101111)%%7, next=(^!(n-2) & e) +^!(n-3)"
n=(0abcdefghi & 0111101111) %%7 求得邻居数对 7 的余数, 在描述 A 中, 由于邻居数 [7,8] 和 [0,1] 的结果是一样的(在中心位置下一代都不会有生命), 所以取余映射不会造成错误
next=(^!(n-2) & e) +^!(n-3) 当 n = 2 时, 取 单元格 e 的值; 当 n = 3 时, 得 1; 其他各种情况, 最后均得 0.
以下是 描述 B 的伪代码
set /a "n=0abcdefghi %% 7, next=^!(n-4) & e | ^!(n-3)"
n=0abcdefghi %% 7 求得总人口数对 7 的余数, 在描述 B 中, 由于人口数 [7,8,9] 和 [0,1,2] 的结果是一样的(在中心位置下一代都不会有生命), 所以取余映射不会造成错误
next=^!(n-4) & e | ^!(n-3) 当 n = 4 时, 取单元格 e 的值; 当 n = 3 时, 得 1; 其他各种情况, 最后得 0.
楼主代码中
xy=^!(xy-2)*(!行%%a:~%%X,2!&1)+^!(xy-3)
也可以写成 ( !行%%a:~%%X,2! 有4种情况: 8进制: 00, 01 十进制: 10, 11 )
xy=^!(xy-2) & !行%%a:~%%X,2! | ^!(xy-3)
以下是测试代码- @echo off & setlocal enableDelayedExpansion
- mode 80,600
- set "A= *"
- for %%a in (0 1) do for %%b in (0 1) do for %%c in (0 1) do for %%d in (0 1) do (
- for %%e in (0 1) do for %%f in (0 1) do for %%g in (0 1) do for %%h in (0 1) do for %%i in (0 1) do (
- set "S=%%a%%b%%c%%d!A:~%%e,1!%%f%%g%%h%%i" & set "S=!S:0=_!"
- REM echo !S!
- set /a "popu=0x%%a%%b%%c%%d%%e%%f%%g%%h %% 15 + %%i"
- REM set /a "n=(0%%a%%b%%c%%d%%e%%f%%g%%h%%i & 0111101111) %% 7, n=^!(n-2) * (%%d%%e & 1) + ^!(n-3)"
- REM set /a "n=(0%%a%%b%%c%%d%%e%%f%%g%%h%%i & 0111101111) %% 7, n=^!(n-2) & %%e | ^!(n-3)"
-
- set /a "n=0%%a%%b%%c%%d%%e%%f%%g%%h%%i %% 7, n=^!(n-4) & %%e | ^!(n-3)"
-
- if !n!==1 (if %%e==0 (set B_!popu! !S!=1) else set S_!popu! !S!=1) else set "D_!popu! !S!=0"
- )
- )
- set B_ & set S_ & set D_
- pause
复制代码
|