2016-12-28 78 views
-5

我有一些代碼,將確定整數N * N列表形成一個魔術方陣:幻方蟒蛇,使用itertools

import itertools 

#Function square magic 
def magic_square(matrix): 
    dimension = len(matrix[0]) 
    sum_list = [] 

    #Horizontal code: 
    sum_list.extend([sum (lines) for lines in matrix]) 

    #Vertical code: 
    for col in range(dimension): 
     sum_list.append(sum(row[col] for row in matrix)) 

    #Diagonals code 
    diagonal1 = 0 
    for i in range(0,dimension): 
     diagonal1 +=matrix[i][i] 
    sum_list.append(diagonal1) 

    diagonal2 = 0 
    for i in range(dimension-1,-1,-1): 
     diagonal2 +=matrix[i][i] 
    sum_list.append(diagonal2) 

    if len(set(sum_list))>1: 
     return False 
    return True 

m=[[7, 12, 1, 14], [2, 13, 8, 11], [16, 3, 10, 5], [9, 6, 15, 4]] 
print(magic_square(m)) 

m=[[2, 7, 6], [9, 5, 1], [4, 3, 8]] 
print(magic_square(m)) 

m=[[2, 7, 6], [9, 5, 1], [4, 3, 7]] 
print(magic_square(m)) 

print("**************************") 

#Now, i use itertools like this: 
for i in itertools.combinations(range(1,10), 3): 
    if sum(i) == 15: 
     print (i) 
# I get the combinations each of three numbers with sum 15 

我的問題是最後一部分:我想生成所有排列的整數1到N^2,將每個分成一個N行和N列的正方形 - 二維列表 - 並使用我的函數查找所有幻方。我寫的代碼找到了3個數字的組合,可以完成這項工作,但我無法弄清楚組合形成正方形。

感謝@Prune的幫助。

如果我有:
[1 5 9]
[1 6 8]
[2 4 9]
[2 5 8]
[2 6 7]
[3 4 8]
[3 5 7]
[4 5 6]
我該如何生成一個方形魔術並知道它是真的?錯誤,一次使用三個矩陣元素?
實施例:
[[1 5 9],[1 6 8],[2 4 9]]

[[1 5 9],[1 6 8],[2 5 8]]

[ [1 5 9],[1 6 8],[2 6 9]]等等等等。

+2

...你有問題嗎?請閱讀[問]。 – jonrsharpe

+1

我明白要求...給我幾分鐘的時間來編輯和澄清。 – Prune

+0

感謝@Prune的幫助。 – Andreas

回答

0

我看到了 - 您想要生成所有幻方的排列。您需要覆蓋範圍從1到N^2,返回爲N列表中的所有排列N N個元素。

import itertools 

N = 3 
for seq in itertools.permutations(range(1, N*N+1)): 
    # Split the sequence into a candidate magic square, 
    # N rows of N elements each. 
    cand = [seq[i:i+N] for i in range(0, N*N, N)] 

這產生了一系列候選正方形;反過來,每一個餵你的檢查程序,並打印出來的那些。我希望你能處理那部分。

這裏有從一代的早期幾個樣品候選人:

[(1, 3, 5), (6, 2, 8), (4, 7, 9)] 
[(1, 3, 5), (6, 2, 8), (4, 9, 7)] 
[(1, 3, 5), (6, 2, 8), (7, 4, 9)] 
[(1, 3, 5), (6, 2, 8), (7, 9, 4)] 
[(1, 3, 5), (6, 2, 8), (9, 4, 7)] 
[(1, 3, 5), (6, 2, 8), (9, 7, 4)] 
[(1, 3, 5), (6, 2, 9), (4, 7, 8)] 
[(1, 3, 5), (6, 2, 9), (4, 8, 7)] 
[(1, 3, 5), (6, 2, 9), (7, 4, 8)] 
[(1, 3, 5), (6, 2, 9), (7, 8, 4)] 
[(1, 3, 5), (6, 2, 9), (8, 4, 7)] 
[(1, 3, 5), (6, 2, 9), (8, 7, 4)] 
方法

變化

注意,這是你原來的算法:這會產生整個方塊,而不僅僅是3行。獨立代有一個邏輯缺陷,因爲它會產生不包括所有9個數字的幻方,而複製其他。例如:

7 2 6 
4 5 6 
4 8 3 
+0

謝謝,@Prune,但我一直在採取嬰兒的步驟,但沒有你的支持,我沒有得到任何地方。 – Andreas

+0

那裏還有其他問題嗎?雙「但」不明確。 – Prune

+0

如果你被卡住了,你還沒有解釋如何。 – Prune

0

算法從給定的停車點

您目前有三個不同的整數1-9那筆15.所有八個可能的組合解決了直截了當的方式幻方的你要求,我建議這些步驟:

  • 生成每個組合的所有排列:每個組合六個,總共48個。一種方法是在當前代碼中生成所有排列(而不是組合)。
  • 考慮這些行一次排列3個排列。對於每個排列,檢查是否堆疊生成的訂單中的行形成一個正方形。你可以檢查:
    • 三列中的每一列總和爲15?
    • 每個對角線總和爲15嗎?
    • 9個數字是唯一的嗎?

更快的代碼

有多種方法來攻擊排列的效率。例如,將行按最低元素(1,2,3或4)分成四組。在生成你的方塊時,從每組中選擇不超過一行。這將大大減少您檢查的總平方,因爲它減少了元素的重複。

另一種方法是先挑選前兩行,然後從列總和中推導出第三行。然後,您只需進行四項檢查:兩個對角線總和爲15,生成的最下一行是合法的(只有數字1-9),並且沒有重複的數字。

尋找8行更有效地

您不必通過720個三元爪子找到8行。相反,生成90個起始對;對於每一個,派生第三個元素(15減去前兩個)。如果第三個元素是7個缺失數字(1-9,但不是前兩個)中的一個,那麼它就是你想要的行之一。

我希望這會引導您找到解決方案。