teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

修正と検証コード追記

2017/12/01 08:46

投稿

8524ba23
8524ba23

スコア38352

answer CHANGED
@@ -1,4 +1,91 @@
1
1
  - 1~K*(K-1) (= 1~12)の数値から相異なるK(=4)個を選ぶ。
2
- - 上記のK個の相異なる2つの差がすべて = (4*(3-1)/2 =6種類)異なる。
2
+ - 上記のK個の相異なる2つの差がすべて( =4!=12種類)異なる。
3
3
 
4
- ものを選べばいけると思います。
4
+ ものを選べばいけると思います。
5
+
6
+ a...dの制約条件がうまく決めきれませんでしたが
7
+ 以下pythonコードで全探索と上記の手法とで結果が一致したので正しいと思います。
8
+
9
+ K=2で2個, K=3で12個, K=4で96個, K=5で240個
10
+ ```Python
11
+ import itertools
12
+
13
+ K = 4 # 正方行列 K * K
14
+ NUM_CNT = K*(K-1) # 対角線以外を埋める数値の個数
15
+ NUMS = [i+1 for i in range(NUM_CNT)] # a...nの走査範囲値 1...NUM_CNT (= K*(K-1) )
16
+ #NUMS = [i for i in range(NUM_CNT+1)]
17
+
18
+ # 循環数を返す -1 = NUM_CNT, -2 = NUM_CNT-1, ...
19
+ def circleNum( n):
20
+ if n < 0:
21
+ n += NUM_CNT+1
22
+ return n
23
+
24
+ # 数値リストから行列を作成
25
+ def getMat( nums):
26
+ return [[circleNum( nums[i]-nums[j]) for j in range(K)] for i in range(K)]
27
+
28
+ # 重複判定 : 行列から
29
+ def isMatDup( mat):
30
+ dup = set()
31
+ for i,j in itertools.product([k for k in range(K)], repeat=2): # 直積
32
+ if i != j:
33
+ if mat[i][j] in dup:
34
+ return True
35
+ dup.add(mat[i][j])
36
+ return False
37
+
38
+ # 重複判定 : 数値リストから
39
+ def isNumDup( nums):
40
+ dup = set()
41
+ for n in itertools.permutations(nums, 2): # 順列
42
+ diff = circleNum(n[0] - n[1])
43
+ if diff in dup:
44
+ return True
45
+ dup.add(diff)
46
+ return False
47
+
48
+
49
+ # 計算 : 全探索+行列から判定
50
+ def calc1( path):
51
+ print(path)
52
+ with open(path, 'w') as f:
53
+ dup = set() # 解(行列)の重複チェック用
54
+ lopCnt,dupCnt,okCnt = 0,0,0
55
+ for nums in itertools.product(NUMS, repeat=K): # 直積
56
+ mat = getMat( nums)
57
+ if not isMatDup(mat):
58
+ key = str(mat)
59
+ if key not in dup:
60
+ f.write( 'nums[%s] mat[%s]\n'%(nums,mat))
61
+ okCnt += 1
62
+ dup.add(key)
63
+ else:
64
+ dupCnt += 1
65
+ lopCnt += 1
66
+ f.write( 'lop[%d] dup[%d] ok[%d]\n'%(lopCnt,dupCnt,okCnt))
67
+
68
+
69
+ # 計算 : 順列+数値リストから判定
70
+ def calc2( path):
71
+ print(path)
72
+ with open(path, 'w') as f:
73
+ dup = set() # 解(行列)の重複チェック用
74
+ lopCnt,dupCnt,okCnt = 0,0,0
75
+ for nums in itertools.permutations(NUMS, K): # 順列
76
+ if not isNumDup(nums):
77
+ mat = getMat(nums)
78
+ key = str(mat)
79
+ if key not in dup:
80
+ f.write( 'nums[%s] mat[%s]\n'%(nums,mat))
81
+ okCnt += 1
82
+ dup.add(key)
83
+ else:
84
+ dupCnt += 1
85
+ lopCnt += 1
86
+ f.write( 'lop[%d] dup[%d] ok[%d]\n'%(lopCnt,dupCnt,okCnt))
87
+
88
+ if __name__ == '__main__':
89
+ calc1('calc1.txt')
90
+ calc2('calc2.txt')
91
+ ```