用itertools的排列迭代器求解三阶幻方

三阶幻方求解一般先已知9个数中的三个数(用ABC表示),然后找出另外6个数的数值和位置,常规方式用数学技巧、口诀、推理进行。本文尝试采用数学的穷举法求解,此法简单粗暴,只是排列迭代器应用。具体方式:将已知的三个数(ABC)和剩余将有效数值(1~19除ABC外)无重复元素排列得到多组的六个数,然后将ABC插入每组相应位置,合并成三阶幻方的九个数,逐一试错,最终得到正确答案。
求解中需用到itertools的排列迭代器,分别为product()和permutations(),它们的区别可以通过以下例子一目了然。

import itertools as it
lisA=[1,2,3]
lisB=[]
lisC=[]
for x in it.permutations(lisA,2):
    lisB.append(x)
print("B",lisB)
for x in it.product(lisA,repeat=2):
    lisC.append(x)
print("C",lisC)

结果显示
B [(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
C [(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
可以看出permutations()无重复元素。在求解三阶幻方中用到permutations()。
以下是最大数为19的三阶幻方求解代码:

#穷举法解3阶幻方

import time
import itertools as it
t1=time.time()
print("输入限制:行和列不大于3,数值不大于19。")
#输入9宫格三个已知数。
w0=input("第一个数(行,列,数值):")
x0=[int(w0[0]),int(w0[2]),int(w0[4:])]
w1=input("第二个数(行,列,数值):")
x1=[int(w1[0]),int(w1[2]),int(w1[4:])]
w2=input("第三个数(行,列,数值):")
x2=[int(w2[0]),int(w2[2]),int(w2[4:])]

#在1-19的数中去掉已知的三个数,形成一个数列。
def f_listFr():
    sl50=[]
    for i in range(1,20):
        sl50.append(i)
    sl50.remove(x0[2])
    sl50.remove(x1[2])
    sl50.remove(x2[2])
    return sl50

#核实数列是否为所求答案
def pdzq(slsxl):
    #下面数列24数字分为8组,每组3个数表示三个9宫格位置。
    sl60=[0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 3, 6, 1, 4, 7, 2, 5, 8, 0, 4, 8, 2, 4, 6]
    #求第一行和
    c=slsxl[0]+slsxl[1]+slsxl[2]
    #判断各行列是否相等
    n=3
    while n<24:
        if slsxl[sl60[n]]+slsxl[sl60[n+1]]+slsxl[sl60[n+2]]==c:
            n+=3
            continue
        else:
            return False
    print("c=",c)
    return True

def f_sl6Frsl(sl50):
    jg=0
    #去掉已知三个数的1-19数列,用排列方式形成新的6个数的数列。
    for slx in it.permutations(sl50, 6):
        slxls=list(slx)
        #将已知三个数插入对应位置,形成9个数的数列。
        w0=(x0[0]-1)*3+x0[1]-1
        slxls.insert(w0,x0[2])
        w1=(x1[0]-1)*3+x1[1]-1
        slxls.insert(w1,x1[2])
        w2=(x2[0]-1)*3+x2[1]-1
        slxls.insert(w2,x2[2])
        #判断数列是否满足要求。
        if not pdzq(slxls):
            continue
        jg+=1
        print(slxls[:3])
        print(slxls[3:6])
        print(slxls[6:])
        print()
    t2=time.time()
    print("找到",jg,"答案。","用了",int(t2-t1),"秒")
sl50=f_listFr()
f_sl6Frsl(sl50)

运行实例:
输入限制:行和列不大于3,数值不大于19。
第一个数(行,列,数值):2,3,8
第二个数(行,列,数值):3,2,6
第三个数(行,列,数值):3,3,13
c= 30
[7, 14, 9]
[12, 10, 8]
[11, 6, 13]

找到 1 答案。 用了 66 秒

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值