Python数独求解器速度慢

时间:2014-12-09 19:18:13

标签: python recursion sudoku backtracking

所以,我用BackTracking算法创建了一个数独求解器。一切都像魅力一样,但与用java编写的相同解决方案相比,解算器真的很慢。 python真的那么慢,或者我的代码中有一个我错过的主要错误? 这是代码:

rida = 0
veerg = 0
maatriks = []
regioon = True
regioonid = []
abimaatriks = [[],[],[],[],[],[],[],[],[]]

# Loeb failist maatriksi sisse ja teeb temast listide listi.
def looMaatriks(sisendfail, maatriks):
    fail = open(sisendfail)
    for line in fail:
        line = line.strip()
        if line != "":
            rida = line.split(" ")
            for i in range (0, 9):
                if rida[i] != "-":
                    rida[i] = int(rida[i])
                else:
                    rida[i] = 0
            maatriks.append(rida)
    return maatriks

maatriks = looMaatriks('sisend1.txt', maatriks)

# Loob failist regiooni.
def looRegioon(sisendfail, reg):
    fail = open(sisendfail)
    for line in fail:
        line = line.strip()
        if line != "":
            rida = line.split(" ")
            reg.append(rida)
            for i in range(0,9):
                rida[i] = int(rida[i])
    return reg

regioonid = looRegioon('sisend2.txt', regioonid)
print(regioonid)

# Loob abimaatriksi, kus regioone säilitada.
def looAbiMaatriks(regioon, abimaatriks):
    for i in range (0, 9):
        for j in range (0, 9):
            abi = regioon[i][j]
            abimaatriks[abi-1].append((i, j))            

looAbiMaatriks(regioonid, abimaatriks)
print(abimaatriks)

# Kontrollib, kas antud ruudukeses on number juba või mitte.
def numberOlemas(maatriks, rida, veerg):
    if maatriks[rida][veerg] != 0:
        return True
    else:
        return False

# Kontrollib, kas arv sobib antud ruutu.
def kasSobib(maatriks, rida, veerg, arv):
    for i in range (0, 9):
        if arv == maatriks[rida][i]:
            return False
    for i in range (0, 9):
        if arv == maatriks[i][veerg]:
            return False
    if regioon == False:
        reaalgus = 3*int(rida/3)
        veerualgus = 3*int(veerg/3)
        for k in range(reaalgus, reaalgus + 3):
            for l in range(veerualgus, veerualgus + 3):
                if arv == maatriks[k][l]:
                    return False
    else:
        abi = regioonid[rida][veerg]
        for i in abimaatriks[abi-1]:
            if maatriks[i[0]][i[1]] == arv:
                return False
    return True

# Prindib maatriksi ilusal kujul välja.
def prindiMaatriks(maatriks):
    for i in range (0, 9):
        print(maatriks[i])
    print("")

# Peafunktsioon, mis lahendab kogu maatriksi rekursiivselt.
def lahendaRuut(maatriks, rida, veerg):
    if veerg > 8:
        veerg = 0
        rida += 1
    if rida == 9:
        return True
    if numberOlemas(maatriks, rida, veerg) == True:
        return lahendaRuut(maatriks, rida, veerg+1)
    for i in range(1,10):
        if kasSobib(maatriks, rida, veerg, i):
            maatriks[rida][veerg] = i
            if lahendaRuut(maatriks, rida, veerg+1):
                return True
            else:
                maatriks[rida][veerg] = 0
    return False

print ("Esialgne maatriks:")
prindiMaatriks(maatriks)

print("Lahendatud maatriks:")
lahendaRuut(maatriks, rida, veerg)

prindiMaatriks(maatriks)

这是sisend1.txt的输入:

- - - - - - - - -

- - - - - - - - -

- - - - - - - - -

- - - - - - - - -

- - - - - - - - -

- - - - - - - - -

- - - - - - - - -

- - - - - - - - -

- - - - - - - - -

这是sisend2.txt的输入:

1 1 1 2 3 3 3 3 3

1 1 1 2 2 2 3 3 3

1 4 4 4 4 2 2 2 3

1 1 4 5 5 5 5 2 2

4 4 4 4 5 6 6 6 6

7 7 5 5 5 5 6 8 8

9 7 7 7 6 6 6 6 8

9 9 9 7 7 7 8 8 8

9 9 9 9 9 7 8 8 8

Input2包含自定义数独的3x3区域。 如果您想在没有区域的情况下进行测试,只需在开头更改regioon = False即可。 输入1只是一个空的数独填充。

1 个答案:

答案 0 :(得分:1)

使用列表推导和一些内置函数还有改进的空间。

例如,而不是:

 rida = line.split(" ")
 for i in range (0, 9):
      if rida[i] != "-":
          rida[i] = int(rida[i])
      else:
          rida[i] = 0

您可以使用列表推导并执行:

rida = line.split(" ")
rida = [int(r) if r != "-" else 0 for r in rida]

还消除了一些内置函数的for循环,例如

for i in range(0,9):
    rida[i] = int(rida[i])

使用地图:

map(int, rida)

同时删除不必要的for循环。替换:

for i in range (0, 9):
    if arv == maatriks[rida][i]:
        return False
for i in range (0, 9):
    if arv == maatriks[i][veerg]:
        return False

使用:

for i in rage(0, 9):
    if arv in [maatriks[rida][i], maatriks[i][veerg]]:
        return False