知恵袋で見つけた判断推理のロッカーの位置関係の問題をPythonで解いてみました。(^_^;
A〜Lの12人はあるスポーツクラブの会員であり、それぞれ、図のように配置された1番から12番までのロッカーのいずれか一つを個人ロッカーとして使用している。今、次の事が分かっている時、Dが使用している可能性があるロッカーを全て挙げているのはどれか。なお、1番のロッカーの周りのロッカーとは、2番、5番、6番のロッカーを指すものとする。
ア.Aのロッカーの周りのロッカーは3個で、それらは、E、I、Jのロッカーである。
イ.Bのロッカーの周りのロッカーは8個で、その中にFのロッカーはない。
ウ.Cのロッカーの1つ斜め上はB、Eのロッカーである。
エ.Lのロッカーは、左端の列(1番、5番、9番)にある。
オ.G、I、Lのロッカーの周りにはそれぞれ5個のロッカーがある。
<選択肢>
1.1,9
2.1,2,12
3.1,2,9,10
4.2,10
5.2,7,10,12
※ただし、条件にア〜オの名前を付けました。(^_^;
+--+--+--+--+ | 1| 2| 3| 4| 1行目 +--+--+--+--+ | 5| 6| 7| 8| 2行目 +--+--+--+--+ | 9|10|11|12| 3行目 +--+--+--+--+ 1 2 3 4 : 列目
12個の順列は時間がかかるので枝が早く刈れそうなA,B,E,I,J,Lをループの前の方に持ってきて、残りを順列で回してみました。(^_^;
● Locker1.py
# coding: UTF-8 # Locker1.py from time import time import itertools MR = 3 # 行の最大数 MC = 4 # 列の最大数 # 通し番号n番目の行数を得る def getRow(n): return (n-1)//MC+1 # n番の列数を得る def getCol(n): return (n-1)%MC+1 # r行c列の通し番号を得る def getN(r,c): if r< 1 or MR< r: return 0 # ドメインエラーは0を返す if c< 1 or MC< c: return 0 return (r-1)*MC+(c-1)+1 # n番のロッカーの周りのロッカーの番号のリストを得る def getSurroundings(n): li = [] if n< 1 or MR*MC< n: return li r,c = getRow(n),getCol(n) for i in range(-1,2): for j in range(-1,2): if i*i+j*j==0: continue m = getN(r+i,c+j) if m!=0: li.append(m) return li # 結果を表示 def PrintResult(cnt,li): n = len(li) NAME = 'ABCDEFGHIJKL' print('[%2d]'%cnt) s = '' for i in range(n): s+=NAME[li.index(i+1)] print(s[:4]+'\n'+s[4:8]+'\n'+s[8:]) print('') def main(): tm = time() # Timer Start P = range(1,12+1) # 1から12番のロッカーの周りのロッカーの番号のリストのリスト(※先頭はダミー) SA = [getSurroundings(n) for n in range(12+1)] S3 = [n for n in range(12+1) if len(SA[n])==3] # 周りのロッカー数が3個のロッカー番号リスト S5 = [n for n in range(12+1) if len(SA[n])==5] # 周りのロッカー数が5個のロッカー番号リスト S8 = [n for n in range(12+1) if len(SA[n])==8] # 周りのロッカー数が8個のロッカー番号リスト ## print(SA); print(S3,S5,S8) ld = [] # Dが使用している可能性があるロッカー番号のリスト cnt = 0 for a in S3: # 条件ア for e,i,j in itertools.permutations(SA[a]): # 条件ア for b in S8: # 条件イ for l in (1,5,9): # 条件エ if l not in S5: continue # 条件オ Q = list(set(P)-set([a,b,e,i,j,l])) if len(Q)!=12-6: continue # ダブっていないか調べる for q in itertools.permutations(Q): c,d,f,g,h,k = q if f in SA[b]: continue # 条件イ rc,cc = getRow(c),getCol(c) # Cのロッカーの行、列 ul = getN(rc-1,cc-1) # Cのロッカーの左上のロッカー番号 ur = getN(rc-1,cc+1) # Cのロッカーの右上のロッカー番号 if set([ul,ur])!=set([b,e]): continue # 条件ウ if g not in S5: continue # 条件オ if i not in S5: continue # 条件オ # チェックを潜り抜けたものだけを表示 cnt+=1 PrintResult(cnt,[a,b,c,d,e,f,g,h,i,j,k,l]) # 選択肢のチェック用 if d not in ld: ld.append(d) print(u'∴ %s'%ld) print("Runtime : %.3f [sec]"%(time()-tm)) # Timer Stop & Disp if __name__ == '__main__': main()
●実行結果
[ 1] DGIA LBJE HKCF [ 2] DGIA LBJE KHCF …(省略)… [12] KGIA LBJE HDCF ∴ [1, 2, 9, 10] Runtime : 0.016 [sec]
※参考URL
●SEND MORE MONEY in Python(3) - rscの日記
●判断推理の部屋の位置関係の問題をPythonで解いてみた。 - rscのブログ
●日能研のマインスイーパーに似たボードパズルの問題をPythonで解いてみた。 - rscのブログ
●判断推理の家の位置関係の問題をPythonで解いてみた。 - rscのブログ
●判断推理の家の位置関係の問題をPythonで解いてみた。(2) - rscのブログ