幻方,也称九宫格,宋代数学家杨辉称之为纵横图,是我国一种传统数字游戏。幻方是将从1到若干个数的自然数排成纵横各为若干个数的正方形,使在同一行、同一列和同一对角线上的几个数的和都相等。古时候幻方经常在官府、学堂等场所出见,后来通过印度、阿拉伯等地传到西方,因其奇幻的特性,被称为Magic Square,即“幻方”或“魔方”。
传说上古伏羲氏时,有龙马从黄河里跳出来,背上负着河图;有神龟从洛水里跳出来,背上负有洛书。伏羲氏根据河图、洛书演化成八卦。洛书便是最早的幻方,用现代数学语言解释,就是用1~9九个数字,填在九个格子里,使每一横行、每一竖列以及两条对角线上3个数字的和都等于15。
《射雕英雄传》里面有一个情节,郭靖带着受伤的黄蓉四处求高人疗伤,遇见瑛姑。瑛姑也爱好各种奇门术数,但是花了好多年却解不出一个三阶幻方。这个三阶幻方也就是“洛书”,它有三行三列,九个空格分别填上一到九这九个数字,使得每行、每列、每条对角线上三个数的和都相等。
黄蓉是黄老邪的女儿,古灵精怪,自然也精通此道,很快告诉了瑛姑答案。于是瑛姑就告诉郭靖黄蓉可以找段皇爷疗伤。当然瑛姑其实也是为了找段皇爷寻仇。这是后话。其实三阶的幻方太简单了。我倒觉得金庸可以可以把这一段情节改成瑛姑解的是一个五阶幻方,就是五行五列的幻方,甚至是七行七列的幻方,这样花十几年解不出也情有可原,难度大些,瑛姑也不至于显得那么笨。不知道金庸是不是为了衬托黄蓉的聪明?她的口诀是:九宫之义,法以灵龟,二四为肩,六八为足,左七右三,戴九履一,五居中央。
当N为奇数时的幻方解法如下:
⑴ 将1放在第一行中间一列;
⑵ 从2开始直到n×n止各数依次按下列规则存放:按 45°方向行走,如向右下每一个数存放的行比前一个数的行数减1,列数加1
⑶ 如果行列范围超出矩阵范围,则回绕。例如1在第1行,则2应放在最上一行,列数同样加1;
⑷ 如果按上面规则确定的位置上已有数,或上一个数是第1行第n列时,则把下一个数放在上一个数的上面。
Python代码如下:
import numpy as np
def hunderdgroup(n):
row, col = n-1, n-1
cur_row, cur_col = 0, int((n-1)/2)
a = 1
group = np.zeros((n, n), dtype=np.int32)
group[cur_row, cur_col] = a
while a < n*n:
a += 1
cur_row = cur_row - 1
cur_col = cur_col + 1
if cur_row < 0 and cur_col > col: # 全部出界
cur_row = cur_row + 2
cur_col = cur_col - 1
group[cur_row, cur_col] = a
elif cur_row < 0 and cur_col <= col: # 行出界
cur_row = row
group[cur_row, cur_col] = a
elif cur_row >= 0 and cur_col > col: # 列出界
cur_col = 0
group[cur_row, cur_col] = a
elif group[cur_row, cur_col] != 0: # 右上角有值
cur_row = cur_row + 2
cur_col = cur_col - 1
group[cur_row, cur_col] = a
else:
group[cur_row, cur_col] = a
sum_row = group.cumsum(axis=0)[n-1]
sum_col = group.cumsum(axis=1)[:, n-1]
print(f"最终矩阵为:\n{group}")
print(f"每一列累加和:{sum_col}")
print(f"每一行累加和:{sum_row}")
if __name__ == "__main__":
n = int(input("请输入一个奇数n:"))
hunderdgroup(n)
运行结果如下