回答編集履歴

1

修正と検証コード追記

2017/12/01 08:46

投稿

can110
can110

スコア38262

test CHANGED
@@ -1,7 +1,181 @@
1
1
  - 1~K*(K-1) (= 1~12)の数値から相異なるK(=4)個を選ぶ。
2
2
 
3
- - 上記のK個の相異なる2つの差がすべて = (4*(3-1)/2 =6種類)異なる。
3
+ - 上記のK個の相異なる2つの差がすべて( =4!=12種類)異なる。
4
4
 
5
5
 
6
6
 
7
7
  ものを選べばいけると思います。
8
+
9
+
10
+
11
+ a...dの制約条件がうまく決めきれませんでしたが
12
+
13
+ 以下pythonコードで全探索と上記の手法とで結果が一致したので正しいと思います。
14
+
15
+
16
+
17
+ K=2で2個, K=3で12個, K=4で96個, K=5で240個
18
+
19
+ ```Python
20
+
21
+ import itertools
22
+
23
+
24
+
25
+ K = 4 # 正方行列 K * K
26
+
27
+ NUM_CNT = K*(K-1) # 対角線以外を埋める数値の個数
28
+
29
+ NUMS = [i+1 for i in range(NUM_CNT)] # a...nの走査範囲値 1...NUM_CNT (= K*(K-1) )
30
+
31
+ #NUMS = [i for i in range(NUM_CNT+1)]
32
+
33
+
34
+
35
+ # 循環数を返す -1 = NUM_CNT, -2 = NUM_CNT-1, ...
36
+
37
+ def circleNum( n):
38
+
39
+ if n < 0:
40
+
41
+ n += NUM_CNT+1
42
+
43
+ return n
44
+
45
+
46
+
47
+ # 数値リストから行列を作成
48
+
49
+ def getMat( nums):
50
+
51
+ return [[circleNum( nums[i]-nums[j]) for j in range(K)] for i in range(K)]
52
+
53
+
54
+
55
+ # 重複判定 : 行列から
56
+
57
+ def isMatDup( mat):
58
+
59
+ dup = set()
60
+
61
+ for i,j in itertools.product([k for k in range(K)], repeat=2): # 直積
62
+
63
+ if i != j:
64
+
65
+ if mat[i][j] in dup:
66
+
67
+ return True
68
+
69
+ dup.add(mat[i][j])
70
+
71
+ return False
72
+
73
+
74
+
75
+ # 重複判定 : 数値リストから
76
+
77
+ def isNumDup( nums):
78
+
79
+ dup = set()
80
+
81
+ for n in itertools.permutations(nums, 2): # 順列
82
+
83
+ diff = circleNum(n[0] - n[1])
84
+
85
+ if diff in dup:
86
+
87
+ return True
88
+
89
+ dup.add(diff)
90
+
91
+ return False
92
+
93
+
94
+
95
+
96
+
97
+ # 計算 : 全探索+行列から判定
98
+
99
+ def calc1( path):
100
+
101
+ print(path)
102
+
103
+ with open(path, 'w') as f:
104
+
105
+ dup = set() # 解(行列)の重複チェック用
106
+
107
+ lopCnt,dupCnt,okCnt = 0,0,0
108
+
109
+ for nums in itertools.product(NUMS, repeat=K): # 直積
110
+
111
+ mat = getMat( nums)
112
+
113
+ if not isMatDup(mat):
114
+
115
+ key = str(mat)
116
+
117
+ if key not in dup:
118
+
119
+ f.write( 'nums[%s] mat[%s]\n'%(nums,mat))
120
+
121
+ okCnt += 1
122
+
123
+ dup.add(key)
124
+
125
+ else:
126
+
127
+ dupCnt += 1
128
+
129
+ lopCnt += 1
130
+
131
+ f.write( 'lop[%d] dup[%d] ok[%d]\n'%(lopCnt,dupCnt,okCnt))
132
+
133
+
134
+
135
+
136
+
137
+ # 計算 : 順列+数値リストから判定
138
+
139
+ def calc2( path):
140
+
141
+ print(path)
142
+
143
+ with open(path, 'w') as f:
144
+
145
+ dup = set() # 解(行列)の重複チェック用
146
+
147
+ lopCnt,dupCnt,okCnt = 0,0,0
148
+
149
+ for nums in itertools.permutations(NUMS, K): # 順列
150
+
151
+ if not isNumDup(nums):
152
+
153
+ mat = getMat(nums)
154
+
155
+ key = str(mat)
156
+
157
+ if key not in dup:
158
+
159
+ f.write( 'nums[%s] mat[%s]\n'%(nums,mat))
160
+
161
+ okCnt += 1
162
+
163
+ dup.add(key)
164
+
165
+ else:
166
+
167
+ dupCnt += 1
168
+
169
+ lopCnt += 1
170
+
171
+ f.write( 'lop[%d] dup[%d] ok[%d]\n'%(lopCnt,dupCnt,okCnt))
172
+
173
+
174
+
175
+ if __name__ == '__main__':
176
+
177
+ calc1('calc1.txt')
178
+
179
+ calc2('calc2.txt')
180
+
181
+ ```