質問編集履歴

8

修正

2020/12/16 00:10

投稿

apeirogon0813
apeirogon0813

スコア117

test CHANGED
File without changes
test CHANGED
@@ -10,6 +10,8 @@
10
10
 
11
11
  import copy
12
12
 
13
+ import sys
14
+
13
15
 
14
16
 
15
17
  #要素が重複しているか
@@ -20,11 +22,45 @@
20
22
 
21
23
 
22
24
 
25
+ def check(v):
26
+
27
+ vmax = 0
28
+
29
+ for i in range(N-1):
30
+
31
+ if v[i] + v[i+1] > vmax:
32
+
33
+ vmax = v[i] + v[i+1]
34
+
35
+ number = i
36
+
37
+ #print("インデックス = " + str(number))
38
+
39
+ #print(v[number])
40
+
41
+ return number
42
+
43
+
44
+
23
45
  def create_volumes(n):
24
46
 
25
47
  #重複しないレコードの作成
26
48
 
27
- V = random.sample(range(5,50), k=n)
49
+ V = random.sample(range(5,500), k=n)
50
+
51
+ Min = min(V)
52
+
53
+ ##print("最小値 = " + str(Min))
54
+
55
+ V.remove(Min)
56
+
57
+ V.insert(0,Min)
58
+
59
+ if check(V) < n/2:
60
+
61
+ return create_volumes(n)
62
+
63
+ #print("V2 = " + str(V))
28
64
 
29
65
  #観測されるボリューム集合の生成
30
66
 
@@ -82,6 +118,10 @@
82
118
 
83
119
 
84
120
 
121
+
122
+
123
+
124
+
85
125
  def create_no_duplicates(n):
86
126
 
87
127
  data = create_volumes(n)
@@ -100,31 +140,37 @@
100
140
 
101
141
 
102
142
 
143
+
144
+
145
+
146
+
147
+
148
+
103
149
  Ans = []
104
150
 
105
- N = 10 #攻撃者は既知
151
+ N = 20 #攻撃者は既知
106
-
152
+
153
+
154
+
107
- result = create_duplicates(N)
155
+ result = create_volumes(N)
108
-
109
- #result = create_no_duplicates(N)
110
156
 
111
157
  V = result[0] #復元したいレコード
112
158
 
113
- print("V = " + str(V))
159
+ #print("V = " + str(V))
114
-
160
+
115
- print("W = " + str(result[1]))
161
+ #print("W = " + str(result[1]))
116
162
 
117
163
  W = list(set(result[1])) #攻撃者が観測するボリュームの集合
118
164
 
119
165
 
120
166
 
121
-
167
+ #print("生成完了")
122
168
 
123
169
  #要素を昇順に
124
170
 
125
171
  W.sort()
126
172
 
127
- print("昇順W = " + str(W) + " ( |W| = " + str(len(W)) +" )")
173
+ #print("昇順W = " + str(W) + " ( |W| = " + str(len(W)) +", 重複数" + str(39-len(W)) + " )")
128
174
 
129
175
 
130
176
 
@@ -146,41 +192,13 @@
146
192
 
147
193
 
148
194
 
195
+ #print("グラフ")
196
+
149
- print("存在する枝 = " + str(G.edges))
197
+ #print("存在する枝(" + str(len(G.edges)) + ") = " + str(G.edges))
150
-
198
+
151
- print("抽出されたボリューム(" + str(len(G.nodes)) +"/" + str(len(W)) +") = " + str(G.nodes))
199
+ #print("抽出されたボリューム(" + str(len(G.nodes)) +"/" + str(len(W)) +") = " + str(G.nodes))
152
-
200
+
153
- print(list(G.neighbors(W[0])))
201
+ #print(list(G.neighbors(W[0])))
154
-
155
-
156
-
157
- #step2 確定レコード選別する
158
-
159
- RNodes = [W[0], W[1]] #レコードは重複しない仮定より1,2番目に小さいボリュームはレコードである
160
-
161
- for i in range(2, N):
162
-
163
- for j in range(i):
164
-
165
- #print("W[i] - W[j] = " + str(W[i]) + " - " + str(W[j]))
166
-
167
- if W[i] - W[j] in W and W[i] != 2 * W[j] : #あるボリュームが確定レコード同士の和である時(その要素が隣同士orレコードであるor両方)
168
-
169
- break
170
-
171
- #else: 和でない場合は次に進める
172
-
173
- #最終的にそのボリュームを生成する確定レコードの2要素の和が存在しない場合、そのボリューム確定レコード
174
-
175
- if j == i-1:
176
-
177
- RNodes.append(W[i])
178
-
179
-
180
-
181
- print("確定レコード = " + str(RNodes))
182
-
183
-
184
202
 
185
203
 
186
204
 
@@ -190,27 +208,117 @@
190
208
 
191
209
  S = []
192
210
 
211
+ T = []
212
+
213
+ t = []
214
+
193
215
  #//集合の中にリストの集合
194
216
 
195
217
  l = list(G.neighbors(W[0]))
196
218
 
197
219
 
198
220
 
221
+ #最大値を生成するボリューム初期解
222
+
223
+ for w in W:
224
+
225
+ if W[-1] - w in W:
226
+
227
+ if w not in t:
228
+
229
+ T.append([w, W[-1]-w])
230
+
231
+ t.append(W[-1]-w)
232
+
233
+ #print("maxx = " + str(T))
234
+
235
+
236
+
237
+ #l2 = list(G.neighbors(W[-1]))
238
+
239
+
240
+
241
+ #最小ボリュームの初期解
242
+
199
243
  for i in l: #一次元配列だとループが回せないため、二次元配列にしておく
200
244
 
201
245
  S.append([W[0],i])
202
246
 
203
247
 
204
248
 
249
+
250
+
251
+ def right_shifts(S,G):
252
+
253
+ T = []
254
+
255
+ for s in S:#各候補解ごとに
256
+
257
+ right_num = len(s) - 1
258
+
259
+ l = list(G.neighbors(s[right_num]))#一番右の要素と隣合うノードを取得
260
+
261
+ for node in l:
262
+
263
+ if node not in s: #同じレコードは存在しないかの判定
264
+
265
+ C = copy.copy(s)
266
+
267
+ C.append(node)
268
+
269
+ if C not in T:
270
+
271
+ T.append(C)
272
+
273
+ return T
274
+
275
+
276
+
277
+ def left_shifts(S,G):
278
+
279
+ T = []
280
+
281
+ for s in S:#各候補解ごとに
282
+
283
+ left_num = 0
284
+
285
+ l = list(G.neighbors(s[left_num]))#一番右の要素と隣合うノードを取得
286
+
287
+ for node in l:
288
+
289
+ if node not in s: #同じレコードは存在しないかの判定
290
+
291
+ C = copy.copy(s)
292
+
293
+ C.insert(0,node)
294
+
295
+ if C not in T:
296
+
297
+ T.append(C)
298
+
299
+ return T
300
+
301
+
302
+
303
+
304
+
205
305
  def right_shift(S,G):
206
306
 
207
307
  #print("S = " + str(S))
208
308
 
209
309
  for i in range(N-2): #解の長さがNになるまで
210
310
 
311
+ #print("現時点の解の長さ = " + str(i))
312
+
211
313
  T = []
212
314
 
315
+ #j = 1
316
+
213
- for s in S: #解の数
317
+ for s in S: #候補解の数
318
+
319
+ #print("候補解の " + str(j) + " 番目")
320
+
321
+ #j += 1
214
322
 
215
323
  if len(s) != N:
216
324
 
@@ -230,7 +338,7 @@
230
338
 
231
339
  T.append(C)
232
340
 
233
- T.append(s)#右に拡張できるがそのノードが終点である可能性があるため
341
+ #T.append(s)#右に拡張できるがそのノードが終点である可能性があるため
234
342
 
235
343
  #print(T)
236
344
 
@@ -306,29 +414,159 @@
306
414
 
307
415
  return T
308
416
 
417
+
418
+
419
+ def uni(R,L):
420
+
421
+ S = R
422
+
423
+ for l in L:
424
+
425
+ flag = 0
426
+
427
+ for r in R:
428
+
429
+ print("l = " + str(l))
430
+
431
+ print("r = " + str(r))
432
+
433
+ if l == r:
434
+
435
+ flag = 1
436
+
437
+ break
438
+
439
+ if flag == 0:
440
+
441
+ S.append(l)
442
+
443
+ return S
444
+
445
+
446
+
447
+ def uni2(R,L):
448
+
449
+ S = R
450
+
451
+ for l in L:
452
+
453
+ S.append(l)
454
+
455
+ return S
456
+
457
+
458
+
459
+ #これまでは、最小のボリュームが真ん中である場合を考慮して両方に拡張しないといけなかった
460
+
309
- T = copy.copy(S)
461
+ #T = copy.copy(S)
310
-
462
+
311
- T = right_shift(T,G)
463
+ #T = right_shift(T,G)
312
-
464
+
313
- T = left_shift(T,G)
465
+ #T = left_shift(T,G)
314
-
466
+
315
- S = left_shift(S,G)
467
+ #S = left_shift(S,G)
468
+
316
-
469
+ SR = []
470
+
471
+ SL = []
472
+
473
+ TR = []
474
+
475
+ TL = []
476
+
477
+ #print(N/2)
478
+
479
+ for i in range(3, int(N/2) + 1):
480
+
481
+ print("i = " + str(i), file=sys.stderr)
482
+
317
- S = right_shift(S,G)
483
+ SR = right_shifts(S,G)
484
+
485
+ SL = left_shifts(S,G)
486
+
487
+ TR = right_shifts(T,G)
488
+
489
+ TL = left_shifts(T,G)
490
+
491
+ S = uni2(SR,SL)
492
+
493
+ T = uni2(TR,TL)
494
+
495
+ print("候補解数S = " + str(len(S)), file=sys.stderr)
496
+
497
+ print("候補解数T = " + str(len(T)), file=sys.stderr)
498
+
499
+ #print("Smin = " + str(len(S)))
500
+
501
+ #print(S)
502
+
503
+ #print("Tmax = " + str(len(T)))
504
+
505
+ #print(T)
506
+
507
+ SS = []
508
+
509
+ for s in S:
510
+
511
+ for t in T:
512
+
513
+ flag = 0
514
+
515
+ for i in s:
516
+
517
+ if i in t:
518
+
519
+ flag = 1
520
+
521
+ break
522
+
523
+ if flag == 0:
524
+
525
+ if s[0] + t[0] in W:
526
+
527
+ SS.append(list(reversed(s)) + t)
528
+
529
+ if s[0] + t[-1] in W:
530
+
531
+ SS.append(t + s)
532
+
533
+ if s[-1] + t[0] in W:
534
+
535
+ SS.append(s + t)
536
+
537
+ if s[-1] + t[-1] in W:
538
+
539
+ SS.append(t + list(reversed(s)))
540
+
541
+ #print(SS)
542
+
543
+
544
+
545
+
546
+
547
+
548
+
549
+
550
+
551
+
552
+
553
+
554
+
555
+
318
556
 
319
557
  #print("解候補 = " + str(T))
320
558
 
321
- print("解の数1 = " + str(len(T)))
559
+ #print("解の数1 = " + str(len(SS)))
322
-
560
+
323
- T = confirm(T)
561
+ #T = confirm(T)
324
-
562
+
325
- S = confirm(S)
563
+ #S = confirm(S)
326
564
 
327
565
  #print("解候補選別T = " + str(T))
328
566
 
329
567
  #print("解候補選別S = " + str(S))
330
568
 
331
- print("解の数2 = " + str(len(T)))
569
+ #print("解の数2 = " + str(len(S)))
332
570
 
333
571
 
334
572
 
@@ -336,23 +574,35 @@
336
574
 
337
575
  #step5 解からボリュームを計算し比較
338
576
 
339
- G1 = compare_volumes(T, W)
577
+ #G1 = compare_volumes(T, W)
340
578
 
341
579
  #print("G1 = " + str(G1))
342
580
 
343
- G2 = compare_volumes(S, W)
581
+ G2 = compare_volumes(SS, W)
344
582
 
345
583
  #print("G2 = " + str(G2))
346
584
 
347
- G3 = G1|G2
585
+ #G3 = G1|G2
348
-
349
-
350
-
586
+
587
+
588
+
351
- print("候補解(" + str(len(G3)) + "個) = " + str(G3))
589
+ #print("候補解(" + str(len(G2)) + "個) = " + str(G2))
352
-
590
+
353
- print("真の解 = " + str(V))
591
+ #print("真の解 = " + str(V))
592
+
593
+
594
+
354
-
595
+ if len(G2) == 1:
596
+
355
-
597
+ print("unique")
598
+
599
+ elif len(G2) > 1:
600
+
601
+ print("Ambiguous")
602
+
603
+ else:
604
+
605
+ print("候補解の数がゼロ")
356
606
 
357
607
  ```
358
608
 

7

修正

2020/12/16 00:10

投稿

apeirogon0813
apeirogon0813

スコア117

test CHANGED
File without changes
test CHANGED
@@ -1,6 +1,360 @@
1
1
  TableView上のFirebaseから読み取ったデータのセルをタップすると
2
2
 
3
-
3
+ ```ここに言語を入力
4
+
5
+ import random
6
+
7
+ import networkx as nx
8
+
9
+ import matplotlib.pyplot as plt
10
+
11
+ import copy
12
+
13
+
14
+
15
+ #要素が重複しているか
16
+
17
+ def has_duplicates(seq):
18
+
19
+ return len(seq) == len(set(seq))
20
+
21
+
22
+
23
+ def create_volumes(n):
24
+
25
+ #重複しないレコードの作成
26
+
27
+ V = random.sample(range(5,50), k=n)
28
+
29
+ #観測されるボリューム集合の生成
30
+
31
+ W = copy.copy(V)
32
+
33
+ for i in range(N-1):
34
+
35
+ W.append(V[i]+V[i+1])
36
+
37
+ return V, W
38
+
39
+
40
+
41
+ #候補解から生成されるボリュームを観測したボリュームと比較
42
+
43
+ def compare_volumes(S, W):
44
+
45
+ T = set()
46
+
47
+ #観測されるボリューム集合の生成
48
+
49
+ for s in S:
50
+
51
+ w = copy.copy(s)
52
+
53
+ for i in range(N-1):
54
+
55
+ w.append(s[i]+s[i+1])
56
+
57
+ if set(w) == set(W):
58
+
59
+ #print(tuple(s))
60
+
61
+ T.add(tuple(s))
62
+
63
+ return T
64
+
65
+
66
+
67
+
68
+
69
+ #1つ以上重複しているボリュームを作成(レコードは重複していない)
70
+
71
+ def create_duplicates(n):
72
+
73
+ data = create_volumes(n)
74
+
75
+ if has_duplicates(data[1]): #重複していないならば
76
+
77
+ return create_duplicates(n)
78
+
79
+ else:
80
+
81
+ return data
82
+
83
+
84
+
85
+ def create_no_duplicates(n):
86
+
87
+ data = create_volumes(n)
88
+
89
+ #print(data[1])
90
+
91
+ if has_duplicates(data[1]):
92
+
93
+ return data
94
+
95
+ else:
96
+
97
+ return create_duplicates(n)
98
+
99
+
100
+
101
+
102
+
103
+ Ans = []
104
+
105
+ N = 10 #攻撃者は既知
106
+
107
+ result = create_duplicates(N)
108
+
109
+ #result = create_no_duplicates(N)
110
+
111
+ V = result[0] #復元したいレコード
112
+
113
+ print("V = " + str(V))
114
+
115
+ print("W = " + str(result[1]))
116
+
117
+ W = list(set(result[1])) #攻撃者が観測するボリュームの集合
118
+
119
+
120
+
121
+
122
+
123
+ #要素を昇順に
124
+
125
+ W.sort()
126
+
127
+ print("昇順W = " + str(W) + " ( |W| = " + str(len(W)) +" )")
128
+
129
+
130
+
131
+ G = nx.Graph()
132
+
133
+ #step1 2頂点の和がボリュームに含まれているのならエッジを追加
134
+
135
+ #連結しているて頂点のみをエッジごと抽出
136
+
137
+ n = len(W)
138
+
139
+ for i in range(n-2):
140
+
141
+ for j in range(i+1,n-1):
142
+
143
+ if W[i] + W[j] in W:
144
+
145
+ G.add_edge(W[i], W[j])
146
+
147
+
148
+
149
+ print("存在する枝 = " + str(G.edges))
150
+
151
+ print("抽出されたボリューム(" + str(len(G.nodes)) +"/" + str(len(W)) +") = " + str(G.nodes))
152
+
153
+ print(list(G.neighbors(W[0])))
154
+
155
+
156
+
157
+ #step2 確定レコード選別する
158
+
159
+ RNodes = [W[0], W[1]] #レコードは重複しない仮定より1,2番目に小さいボリュームはレコードである
160
+
161
+ for i in range(2, N):
162
+
163
+ for j in range(i):
164
+
165
+ #print("W[i] - W[j] = " + str(W[i]) + " - " + str(W[j]))
166
+
167
+ if W[i] - W[j] in W and W[i] != 2 * W[j] : #あるボリュームが確定レコード同士の和である時(その要素が隣同士orレコードであるor両方)
168
+
169
+ break
170
+
171
+ #else: 和でない場合は次に進める
172
+
173
+ #最終的にそのボリュームを生成する確定レコードの2要素の和が存在しない場合、そのボリューム確定レコード
174
+
175
+ if j == i-1:
176
+
177
+ RNodes.append(W[i])
178
+
179
+
180
+
181
+ print("確定レコード = " + str(RNodes))
182
+
183
+
184
+
185
+
186
+
187
+
188
+
189
+ #step3 確定レコードである頂点を通る経路長=N-1である経路
190
+
191
+ S = []
192
+
193
+ #//集合の中にリストの集合
194
+
195
+ l = list(G.neighbors(W[0]))
196
+
197
+
198
+
199
+ for i in l: #一次元配列だとループが回せないため、二次元配列にしておく
200
+
201
+ S.append([W[0],i])
202
+
203
+
204
+
205
+ def right_shift(S,G):
206
+
207
+ #print("S = " + str(S))
208
+
209
+ for i in range(N-2): #解の長さがNになるまで
210
+
211
+ T = []
212
+
213
+ for s in S: #解の数
214
+
215
+ if len(s) != N:
216
+
217
+ right_num = len(s) - 1
218
+
219
+ l = list(G.neighbors(s[right_num]))#一番右の要素と隣合うノードを取得
220
+
221
+ for node in l:
222
+
223
+ if node not in s: #同じレコードは存在しないかの判定
224
+
225
+ C = copy.copy(s)
226
+
227
+ C.append(node)
228
+
229
+ if C not in T:
230
+
231
+ T.append(C)
232
+
233
+ T.append(s)#右に拡張できるがそのノードが終点である可能性があるため
234
+
235
+ #print(T)
236
+
237
+ S = copy.copy(T)
238
+
239
+ #print("S = " + str(S))
240
+
241
+ return S
242
+
243
+
244
+
245
+ #S = right_shift(S)
246
+
247
+
248
+
249
+ #左に拡張
250
+
251
+ def left_shift(S,G):
252
+
253
+ for i in range(N-2):
254
+
255
+ T = []
256
+
257
+ for s in S:
258
+
259
+ #print("s = " + str(s))
260
+
261
+ if len(s) != N:
262
+
263
+ l = list(G.neighbors(s[0]))
264
+
265
+ for node in l:
266
+
267
+ if node not in s: #同じレコードは存在しないかの判定
268
+
269
+ C = copy.copy(s)
270
+
271
+ C.insert(0,node) #先頭に要素を追加
272
+
273
+ if C not in T:
274
+
275
+ T.append(C)
276
+
277
+ T.append(s)
278
+
279
+ S = copy.copy(T)
280
+
281
+ #print("s = " + str(S))
282
+
283
+ return S
284
+
285
+
286
+
287
+ #step4 確定コードが解に含まれているか 現段階では確定レコードを通る効率的なアルゴリズムが考えられていないため
288
+
289
+ def confirm(S):
290
+
291
+ T = []
292
+
293
+ for s in S:
294
+
295
+ if len(s) == N:
296
+
297
+ for i in range(len(RNodes)):
298
+
299
+ if RNodes[i] not in s:
300
+
301
+ break
302
+
303
+ if i == len(RNodes)-1:
304
+
305
+ T.append(s)
306
+
307
+ return T
308
+
309
+ T = copy.copy(S)
310
+
311
+ T = right_shift(T,G)
312
+
313
+ T = left_shift(T,G)
314
+
315
+ S = left_shift(S,G)
316
+
317
+ S = right_shift(S,G)
318
+
319
+ #print("解候補 = " + str(T))
320
+
321
+ print("解の数1 = " + str(len(T)))
322
+
323
+ T = confirm(T)
324
+
325
+ S = confirm(S)
326
+
327
+ #print("解候補選別T = " + str(T))
328
+
329
+ #print("解候補選別S = " + str(S))
330
+
331
+ print("解の数2 = " + str(len(T)))
332
+
333
+
334
+
335
+
336
+
337
+ #step5 解からボリュームを計算し比較
338
+
339
+ G1 = compare_volumes(T, W)
340
+
341
+ #print("G1 = " + str(G1))
342
+
343
+ G2 = compare_volumes(S, W)
344
+
345
+ #print("G2 = " + str(G2))
346
+
347
+ G3 = G1|G2
348
+
349
+
350
+
351
+ print("候補解(" + str(len(G3)) + "個) = " + str(G3))
352
+
353
+ print("真の解 = " + str(V))
354
+
355
+
356
+
357
+ ```
4
358
 
5
359
  didSelectRowAt内に
6
360
 
@@ -71,379 +425,3 @@
71
425
  ご教示願います。
72
426
 
73
427
  ![イメージ説明](c02c797f43213fb92bfcf65f7df76b90.png)
74
-
75
-
76
-
77
- ```ここに言語を入力
78
-
79
- import random
80
-
81
- import networkx as nx
82
-
83
- import matplotlib.pyplot as plt
84
-
85
- import copy
86
-
87
-
88
-
89
- #要素が重複しているか
90
-
91
- def has_duplicates(seq):
92
-
93
- return len(seq) == len(set(seq))
94
-
95
-
96
-
97
- def create_volumes(n):
98
-
99
- #重複しないレコードの作成
100
-
101
- V = random.sample(range(5,500), k=n)
102
-
103
- Min = min(V)
104
-
105
- print("最小値 = " + str(Min))
106
-
107
- V.remove(Min)
108
-
109
- V.insert(0,Min)
110
-
111
- #観測されるボリューム集合の生成
112
-
113
- W = copy.copy(V)
114
-
115
- for i in range(N-1):
116
-
117
- W.append(V[i]+V[i+1])
118
-
119
- return V, W
120
-
121
-
122
-
123
- #候補解から生成されるボリュームを観測したボリュームと比較
124
-
125
- def compare_volumes(S, W):
126
-
127
- T = set()
128
-
129
- #観測されるボリューム集合の生成
130
-
131
- for s in S:
132
-
133
- w = copy.copy(s)
134
-
135
- for i in range(N-1):
136
-
137
- w.append(s[i]+s[i+1])
138
-
139
- if set(w) == set(W):
140
-
141
- #print(tuple(s))
142
-
143
- T.add(tuple(s))
144
-
145
- return T
146
-
147
-
148
-
149
-
150
-
151
- #1つ以上重複しているボリュームを作成(レコードは重複していない)
152
-
153
- def create_duplicates(n):
154
-
155
- data = create_volumes(n)
156
-
157
- if has_duplicates(data[1]): #重複していないならば
158
-
159
- return create_duplicates(n)
160
-
161
- else:
162
-
163
- return data
164
-
165
-
166
-
167
- def create_no_duplicates(n):
168
-
169
- data = create_volumes(n)
170
-
171
- #print(data[1])
172
-
173
- if has_duplicates(data[1]):
174
-
175
- return data
176
-
177
- else:
178
-
179
- return create_duplicates(n)
180
-
181
-
182
-
183
-
184
-
185
- Ans = []
186
-
187
- N = 20 #攻撃者は既知
188
-
189
- result = create_duplicates(N)
190
-
191
- #result = create_no_duplicates(N)
192
-
193
- V = result[0] #復元したいレコード
194
-
195
- print("V = " + str(V))
196
-
197
- print("W = " + str(result[1]))
198
-
199
- W = list(set(result[1])) #攻撃者が観測するボリュームの集合
200
-
201
-
202
-
203
-
204
-
205
- #要素を昇順に
206
-
207
- W.sort()
208
-
209
- print("昇順W = " + str(W) + " ( |W| = " + str(len(W)) +", 重複数" + str(39-len(W)) + " )")
210
-
211
-
212
-
213
- G = nx.Graph()
214
-
215
- #step1 2頂点の和がボリュームに含まれているのならエッジを追加
216
-
217
- #連結しているて頂点のみをエッジごと抽出
218
-
219
- n = len(W)
220
-
221
- for i in range(n-2):
222
-
223
- for j in range(i+1,n-1):
224
-
225
- if W[i] + W[j] in W:
226
-
227
- G.add_edge(W[i], W[j])
228
-
229
-
230
-
231
- print("存在する枝(" + str(len(G.edges)) + ") = " + str(G.edges))
232
-
233
- print("抽出されたボリューム(" + str(len(G.nodes)) +"/" + str(len(W)) +") = " + str(G.nodes))
234
-
235
- print(list(G.neighbors(W[0])))
236
-
237
-
238
-
239
- #step2 確定レコード選別する
240
-
241
- RNodes = [W[0], W[1]] #レコードは重複しない仮定より1,2番目に小さいボリュームはレコードである
242
-
243
- for i in range(2, N):
244
-
245
- for j in range(i):
246
-
247
- #print("W[i] - W[j] = " + str(W[i]) + " - " + str(W[j]))
248
-
249
- if W[i] - W[j] in W and W[i] != 2 * W[j] : #あるボリュームが確定レコード同士の和である時(その要素が隣同士orレコードであるor両方)
250
-
251
- break
252
-
253
- #else: 和でない場合は次に進める
254
-
255
- #最終的にそのボリュームを生成する確定レコードの2要素の和が存在しない場合、そのボリューム確定レコード
256
-
257
- if j == i-1:
258
-
259
- RNodes.append(W[i])
260
-
261
-
262
-
263
- print("確定レコード = " + str(RNodes))
264
-
265
-
266
-
267
-
268
-
269
-
270
-
271
- #step3 確定レコードである頂点を通る経路長=N-1である経路
272
-
273
- S = []
274
-
275
- #//集合の中にリストの集合
276
-
277
- l = list(G.neighbors(W[0]))
278
-
279
-
280
-
281
- for i in l: #一次元配列だとループが回せないため、二次元配列にしておく
282
-
283
- S.append([W[0],i])
284
-
285
-
286
-
287
- def right_shift(S,G):
288
-
289
- #print("S = " + str(S))
290
-
291
- for i in range(N-2): #解の長さがNになるまで
292
-
293
- #print("現時点の解の長さ = " + str(i))
294
-
295
- T = []
296
-
297
- #j = 1
298
-
299
- for s in S: #候補解の数
300
-
301
- #print("候補解の " + str(j) + " 番目")
302
-
303
- #j += 1
304
-
305
- if len(s) != N:
306
-
307
- right_num = len(s) - 1
308
-
309
- l = list(G.neighbors(s[right_num]))#一番右の要素と隣合うノードを取得
310
-
311
- for node in l:
312
-
313
- if node not in s: #同じレコードは存在しないかの判定
314
-
315
- C = copy.copy(s)
316
-
317
- C.append(node)
318
-
319
- if C not in T:
320
-
321
- T.append(C)
322
-
323
- #T.append(s)#右に拡張できるがそのノードが終点である可能性があるため
324
-
325
- #print(T)
326
-
327
- S = copy.copy(T)
328
-
329
- #print("S = " + str(S))
330
-
331
- return S
332
-
333
-
334
-
335
- #S = right_shift(S)
336
-
337
-
338
-
339
- #左に拡張
340
-
341
- def left_shift(S,G):
342
-
343
- for i in range(N-2):
344
-
345
- T = []
346
-
347
- for s in S:
348
-
349
- #print("s = " + str(s))
350
-
351
- if len(s) != N:
352
-
353
- l = list(G.neighbors(s[0]))
354
-
355
- for node in l:
356
-
357
- if node not in s: #同じレコードは存在しないかの判定
358
-
359
- C = copy.copy(s)
360
-
361
- C.insert(0,node) #先頭に要素を追加
362
-
363
- if C not in T:
364
-
365
- T.append(C)
366
-
367
- T.append(s)
368
-
369
- S = copy.copy(T)
370
-
371
- #print("s = " + str(S))
372
-
373
- return S
374
-
375
-
376
-
377
- #step4 確定コードが解に含まれているか 現段階では確定レコードを通る効率的なアルゴリズムが考えられていないため
378
-
379
- def confirm(S):
380
-
381
- T = []
382
-
383
- for s in S:
384
-
385
- if len(s) == N:
386
-
387
- for i in range(len(RNodes)):
388
-
389
- if RNodes[i] not in s:
390
-
391
- break
392
-
393
- if i == len(RNodes)-1:
394
-
395
- T.append(s)
396
-
397
- return T
398
-
399
- #これまでは、最小のボリュームが真ん中である場合を考慮して両方に拡張しないといけなかった
400
-
401
- #T = copy.copy(S)
402
-
403
- #T = right_shift(T,G)
404
-
405
- #T = left_shift(T,G)
406
-
407
- #S = left_shift(S,G)
408
-
409
- S = right_shift(S,G)
410
-
411
- #print("解候補 = " + str(T))
412
-
413
- print("解の数1 = " + str(len(S)))
414
-
415
- #T = confirm(T)
416
-
417
- S = confirm(S)
418
-
419
- #print("解候補選別T = " + str(T))
420
-
421
- #print("解候補選別S = " + str(S))
422
-
423
- print("解の数2 = " + str(len(S)))
424
-
425
-
426
-
427
-
428
-
429
- #step5 解からボリュームを計算し比較
430
-
431
- #G1 = compare_volumes(T, W)
432
-
433
- #print("G1 = " + str(G1))
434
-
435
- G2 = compare_volumes(S, W)
436
-
437
- #print("G2 = " + str(G2))
438
-
439
- #G3 = G1|G2
440
-
441
-
442
-
443
- print("候補解(" + str(len(G2)) + "個) = " + str(G2))
444
-
445
- print("真の解 = " + str(V))
446
-
447
-
448
-
449
- ```

6

修正

2020/11/20 05:00

投稿

apeirogon0813
apeirogon0813

スコア117

test CHANGED
File without changes
test CHANGED
@@ -71,3 +71,379 @@
71
71
  ご教示願います。
72
72
 
73
73
  ![イメージ説明](c02c797f43213fb92bfcf65f7df76b90.png)
74
+
75
+
76
+
77
+ ```ここに言語を入力
78
+
79
+ import random
80
+
81
+ import networkx as nx
82
+
83
+ import matplotlib.pyplot as plt
84
+
85
+ import copy
86
+
87
+
88
+
89
+ #要素が重複しているか
90
+
91
+ def has_duplicates(seq):
92
+
93
+ return len(seq) == len(set(seq))
94
+
95
+
96
+
97
+ def create_volumes(n):
98
+
99
+ #重複しないレコードの作成
100
+
101
+ V = random.sample(range(5,500), k=n)
102
+
103
+ Min = min(V)
104
+
105
+ print("最小値 = " + str(Min))
106
+
107
+ V.remove(Min)
108
+
109
+ V.insert(0,Min)
110
+
111
+ #観測されるボリューム集合の生成
112
+
113
+ W = copy.copy(V)
114
+
115
+ for i in range(N-1):
116
+
117
+ W.append(V[i]+V[i+1])
118
+
119
+ return V, W
120
+
121
+
122
+
123
+ #候補解から生成されるボリュームを観測したボリュームと比較
124
+
125
+ def compare_volumes(S, W):
126
+
127
+ T = set()
128
+
129
+ #観測されるボリューム集合の生成
130
+
131
+ for s in S:
132
+
133
+ w = copy.copy(s)
134
+
135
+ for i in range(N-1):
136
+
137
+ w.append(s[i]+s[i+1])
138
+
139
+ if set(w) == set(W):
140
+
141
+ #print(tuple(s))
142
+
143
+ T.add(tuple(s))
144
+
145
+ return T
146
+
147
+
148
+
149
+
150
+
151
+ #1つ以上重複しているボリュームを作成(レコードは重複していない)
152
+
153
+ def create_duplicates(n):
154
+
155
+ data = create_volumes(n)
156
+
157
+ if has_duplicates(data[1]): #重複していないならば
158
+
159
+ return create_duplicates(n)
160
+
161
+ else:
162
+
163
+ return data
164
+
165
+
166
+
167
+ def create_no_duplicates(n):
168
+
169
+ data = create_volumes(n)
170
+
171
+ #print(data[1])
172
+
173
+ if has_duplicates(data[1]):
174
+
175
+ return data
176
+
177
+ else:
178
+
179
+ return create_duplicates(n)
180
+
181
+
182
+
183
+
184
+
185
+ Ans = []
186
+
187
+ N = 20 #攻撃者は既知
188
+
189
+ result = create_duplicates(N)
190
+
191
+ #result = create_no_duplicates(N)
192
+
193
+ V = result[0] #復元したいレコード
194
+
195
+ print("V = " + str(V))
196
+
197
+ print("W = " + str(result[1]))
198
+
199
+ W = list(set(result[1])) #攻撃者が観測するボリュームの集合
200
+
201
+
202
+
203
+
204
+
205
+ #要素を昇順に
206
+
207
+ W.sort()
208
+
209
+ print("昇順W = " + str(W) + " ( |W| = " + str(len(W)) +", 重複数" + str(39-len(W)) + " )")
210
+
211
+
212
+
213
+ G = nx.Graph()
214
+
215
+ #step1 2頂点の和がボリュームに含まれているのならエッジを追加
216
+
217
+ #連結しているて頂点のみをエッジごと抽出
218
+
219
+ n = len(W)
220
+
221
+ for i in range(n-2):
222
+
223
+ for j in range(i+1,n-1):
224
+
225
+ if W[i] + W[j] in W:
226
+
227
+ G.add_edge(W[i], W[j])
228
+
229
+
230
+
231
+ print("存在する枝(" + str(len(G.edges)) + ") = " + str(G.edges))
232
+
233
+ print("抽出されたボリューム(" + str(len(G.nodes)) +"/" + str(len(W)) +") = " + str(G.nodes))
234
+
235
+ print(list(G.neighbors(W[0])))
236
+
237
+
238
+
239
+ #step2 確定レコード選別する
240
+
241
+ RNodes = [W[0], W[1]] #レコードは重複しない仮定より1,2番目に小さいボリュームはレコードである
242
+
243
+ for i in range(2, N):
244
+
245
+ for j in range(i):
246
+
247
+ #print("W[i] - W[j] = " + str(W[i]) + " - " + str(W[j]))
248
+
249
+ if W[i] - W[j] in W and W[i] != 2 * W[j] : #あるボリュームが確定レコード同士の和である時(その要素が隣同士orレコードであるor両方)
250
+
251
+ break
252
+
253
+ #else: 和でない場合は次に進める
254
+
255
+ #最終的にそのボリュームを生成する確定レコードの2要素の和が存在しない場合、そのボリューム確定レコード
256
+
257
+ if j == i-1:
258
+
259
+ RNodes.append(W[i])
260
+
261
+
262
+
263
+ print("確定レコード = " + str(RNodes))
264
+
265
+
266
+
267
+
268
+
269
+
270
+
271
+ #step3 確定レコードである頂点を通る経路長=N-1である経路
272
+
273
+ S = []
274
+
275
+ #//集合の中にリストの集合
276
+
277
+ l = list(G.neighbors(W[0]))
278
+
279
+
280
+
281
+ for i in l: #一次元配列だとループが回せないため、二次元配列にしておく
282
+
283
+ S.append([W[0],i])
284
+
285
+
286
+
287
+ def right_shift(S,G):
288
+
289
+ #print("S = " + str(S))
290
+
291
+ for i in range(N-2): #解の長さがNになるまで
292
+
293
+ #print("現時点の解の長さ = " + str(i))
294
+
295
+ T = []
296
+
297
+ #j = 1
298
+
299
+ for s in S: #候補解の数
300
+
301
+ #print("候補解の " + str(j) + " 番目")
302
+
303
+ #j += 1
304
+
305
+ if len(s) != N:
306
+
307
+ right_num = len(s) - 1
308
+
309
+ l = list(G.neighbors(s[right_num]))#一番右の要素と隣合うノードを取得
310
+
311
+ for node in l:
312
+
313
+ if node not in s: #同じレコードは存在しないかの判定
314
+
315
+ C = copy.copy(s)
316
+
317
+ C.append(node)
318
+
319
+ if C not in T:
320
+
321
+ T.append(C)
322
+
323
+ #T.append(s)#右に拡張できるがそのノードが終点である可能性があるため
324
+
325
+ #print(T)
326
+
327
+ S = copy.copy(T)
328
+
329
+ #print("S = " + str(S))
330
+
331
+ return S
332
+
333
+
334
+
335
+ #S = right_shift(S)
336
+
337
+
338
+
339
+ #左に拡張
340
+
341
+ def left_shift(S,G):
342
+
343
+ for i in range(N-2):
344
+
345
+ T = []
346
+
347
+ for s in S:
348
+
349
+ #print("s = " + str(s))
350
+
351
+ if len(s) != N:
352
+
353
+ l = list(G.neighbors(s[0]))
354
+
355
+ for node in l:
356
+
357
+ if node not in s: #同じレコードは存在しないかの判定
358
+
359
+ C = copy.copy(s)
360
+
361
+ C.insert(0,node) #先頭に要素を追加
362
+
363
+ if C not in T:
364
+
365
+ T.append(C)
366
+
367
+ T.append(s)
368
+
369
+ S = copy.copy(T)
370
+
371
+ #print("s = " + str(S))
372
+
373
+ return S
374
+
375
+
376
+
377
+ #step4 確定コードが解に含まれているか 現段階では確定レコードを通る効率的なアルゴリズムが考えられていないため
378
+
379
+ def confirm(S):
380
+
381
+ T = []
382
+
383
+ for s in S:
384
+
385
+ if len(s) == N:
386
+
387
+ for i in range(len(RNodes)):
388
+
389
+ if RNodes[i] not in s:
390
+
391
+ break
392
+
393
+ if i == len(RNodes)-1:
394
+
395
+ T.append(s)
396
+
397
+ return T
398
+
399
+ #これまでは、最小のボリュームが真ん中である場合を考慮して両方に拡張しないといけなかった
400
+
401
+ #T = copy.copy(S)
402
+
403
+ #T = right_shift(T,G)
404
+
405
+ #T = left_shift(T,G)
406
+
407
+ #S = left_shift(S,G)
408
+
409
+ S = right_shift(S,G)
410
+
411
+ #print("解候補 = " + str(T))
412
+
413
+ print("解の数1 = " + str(len(S)))
414
+
415
+ #T = confirm(T)
416
+
417
+ S = confirm(S)
418
+
419
+ #print("解候補選別T = " + str(T))
420
+
421
+ #print("解候補選別S = " + str(S))
422
+
423
+ print("解の数2 = " + str(len(S)))
424
+
425
+
426
+
427
+
428
+
429
+ #step5 解からボリュームを計算し比較
430
+
431
+ #G1 = compare_volumes(T, W)
432
+
433
+ #print("G1 = " + str(G1))
434
+
435
+ G2 = compare_volumes(S, W)
436
+
437
+ #print("G2 = " + str(G2))
438
+
439
+ #G3 = G1|G2
440
+
441
+
442
+
443
+ print("候補解(" + str(len(G2)) + "個) = " + str(G2))
444
+
445
+ print("真の解 = " + str(V))
446
+
447
+
448
+
449
+ ```

5

修正

2020/11/20 04:37

投稿

apeirogon0813
apeirogon0813

スコア117

test CHANGED
File without changes
test CHANGED
@@ -71,11 +71,3 @@
71
71
  ご教示願います。
72
72
 
73
73
  ![イメージ説明](c02c797f43213fb92bfcf65f7df76b90.png)
74
-
75
-
76
-
77
-
78
-
79
- PS.[ソースコードです](https://github.com/enpitut2020/LoveJudgement/tree/createPostsList)
80
-
81
- すみません、ソースコードはmasterではなくブランチのcreatePostsListです

4

修正

2020/11/02 12:55

投稿

apeirogon0813
apeirogon0813

スコア117

test CHANGED
File without changes
test CHANGED
@@ -77,3 +77,5 @@
77
77
 
78
78
 
79
79
  PS.[ソースコードです](https://github.com/enpitut2020/LoveJudgement/tree/createPostsList)
80
+
81
+ すみません、ソースコードはmasterではなくブランチのcreatePostsListです

3

ソースコードの修正

2020/11/02 10:34

投稿

apeirogon0813
apeirogon0813

スコア117

test CHANGED
File without changes
test CHANGED
@@ -76,4 +76,4 @@
76
76
 
77
77
 
78
78
 
79
- PS.[ソースコードです](https://github.com/enpitut2020/LoveJudgement.git)
79
+ PS.[ソースコードです](https://github.com/enpitut2020/LoveJudgement/tree/createPostsList)

2

追記

2020/11/02 10:34

投稿

apeirogon0813
apeirogon0813

スコア117

test CHANGED
File without changes
test CHANGED
@@ -71,3 +71,9 @@
71
71
  ご教示願います。
72
72
 
73
73
  ![イメージ説明](c02c797f43213fb92bfcf65f7df76b90.png)
74
+
75
+
76
+
77
+
78
+
79
+ PS.[ソースコードです](https://github.com/enpitut2020/LoveJudgement.git)

1

追記

2020/11/02 10:12

投稿

apeirogon0813
apeirogon0813

スコア117

test CHANGED
File without changes
test CHANGED
@@ -42,7 +42,9 @@
42
42
 
43
43
  ![イメージ説明](ce2de5a6486214bd27851444652acb8b.png)
44
44
 
45
- ![![イメージ説明](bcdd96b7434e3a1433c9d514560537d2.png)]
45
+ ![![イメージ説明](bcdd96b7434e3a1433c9d514560537d2.png)
46
+
47
+ ![イメージ説明](98d508b712a34027f6d37501405184b3.png)
46
48
 
47
49
 
48
50