【Python練習題 017】 兩個乒乓球隊進行比賽,各出三人。甲隊為a,b,c三人,乙隊為x,y,z三人。已抽簽決定比賽名單。有人向隊員打聽比賽的名單。a說他不和x比,c說他不和x,z比。請編程式找出三隊賽手的名單。 這題真真想破我腦袋了,看了好幾份別人的代碼才勉強看懂,真是…… 一開始我只想著先 ...
【Python練習題 017】 兩個乒乓球隊進行比賽,各出三人。甲隊為a,b,c三人,乙隊為x,y,z三人。已抽簽決定比賽名單。有人向隊員打聽比賽的名單。a說他不和x比,c說他不和x,z比。請編程式找出三隊賽手的名單。
------------------------------------------------------
這題真真想破我腦袋了,看了好幾份別人的代碼才勉強看懂,真是…… 一開始我只想著先把所有可能都配出來(ax, ay, az, bx, by, bz, cx, cy, cz),然後根據後面的條件排除不可能的配對。怎麼寫也寫不對。
後來看了別人的代碼,結合自己的思考,整理出基本思路如下:假設a,b,c的對手分別是i,j,k,將i,j,k所有可能出現的組合先窮舉出來,同時需要滿足2個條件:i,j,k不能同時出現(即a,b,c的對手不可能有重覆);a不對x,c不對x,z,只要滿足此2條件就可以。簡而言之:用3個for窮舉,用2個if限定條件。代碼如下:
for i in range(ord('x'), ord('z')+1): #假設a,b,c的對手分別是i,j,k for j in range(ord('x'), ord('z')+1): #用3個for窮舉i,j,k可能出現的所有組合 for k in range(ord('x'), ord('z')+1): if i != j and j != k and k != i: #條件1:i,j,k不能同時出現 if i != ord('x') and k != ord('x') and k != ord('z'): #條件2:a不對x,c不對x,z print('a vs %s, b vs %s, c vs %s' % (chr(i), chr(j), chr(k)))
輸出結果如下:
a vs z, b vs x, c vs y
根據上述代碼,聯想到之前 求解不重覆的3位數 時用到的itertools庫,覺得可以簡化代碼如下:
import itertools for i in itertools.permutations('xyz'): if i[0] != 'x' and i[2] != 'x' and i[2] != 'z': print('a vs %s, b vs %s, c vs %s' % (i[0], i[1], i[2]))
輸出結果一樣。代碼簡潔很多,結構也清晰不少。
itertools.permutations()是個好東西,可以直接將'xyz'生成包含所有排列的列表。另外兩個相關的庫方法分別是:itertools.product()生成笛卡爾數列(即包括所有排列方式,itertools.combinations()生成所有組合的列表。就生成項的數目而言,product() > permutations() > combinations()。本題中,permutations('xyz', 3)可生成6組排列方式,而如果換成combinations('xyz', 3),則只有1種組合方式('x', 'y', 'z')。詳見官方文檔。
++++++++++++++++++++++++++++++++++++++