回答編集履歴

2

追記

2019/01/19 03:48

投稿

LouiS0616
LouiS0616

スコア35660

test CHANGED
@@ -398,6 +398,16 @@
398
398
 
399
399
 
400
400
 
401
+ 細かにテストを挟むことで、バグ発生時の調査範囲は激減します。
402
+
403
+ 今、目の前で実装したばかりのコードを重点的に調べれば良いなら、とても楽だと思いませんか。
404
+
405
+
406
+
407
+ もちろん、段階を踏んで作っていっても、過程のバグに気付けない場合もありますが。
408
+
409
+
410
+
401
411
  コード
402
412
 
403
413
  ---

1

追記

2019/01/19 03:48

投稿

LouiS0616
LouiS0616

スコア35660

test CHANGED
@@ -17,3 +17,573 @@
17
17
  }
18
18
 
19
19
  > ```
20
+
21
+
22
+
23
+ コードの組み方
24
+
25
+ ---
26
+
27
+ 一通りコードを完成させてからバグを解消するのは困難です。
28
+
29
+ 小さな、でも確かに動作するコードを組み立てていった方がスムーズでしょう。
30
+
31
+
32
+
33
+ ######ステップ1: binary_search関数の実装と簡易なテスト
34
+
35
+ グローバル変数を使わないように少し改造してますが、ざっくりこんな感じで組みます。
36
+
37
+ ```C++
38
+
39
+ bool binary_search(int sorted_arr[], size_t len, int purpose) {
40
+
41
+ int left = 0;
42
+
43
+ int right = len;
44
+
45
+
46
+
47
+ while (right - left >= 1) {
48
+
49
+ int middle = (left + right) / 2;
50
+
51
+
52
+
53
+ if (sorted_arr[middle] == purpose) {
54
+
55
+ return true;
56
+
57
+ }
58
+
59
+
60
+
61
+ if (sorted_arr[middle] < purpose) {
62
+
63
+ left = middle + 1;
64
+
65
+ }
66
+
67
+ else {
68
+
69
+ right = middle;
70
+
71
+ }
72
+
73
+ }
74
+
75
+
76
+
77
+ return false;
78
+
79
+ }
80
+
81
+ ```
82
+
83
+
84
+
85
+ ダミーデータで動作を確認します。
86
+
87
+ ```C++
88
+
89
+ int main(void) {
90
+
91
+ int arr[] = {1, 3, 5, 7, 9};
92
+
93
+ size_t len = std::size(arr);
94
+
95
+
96
+
97
+ printf(
98
+
99
+ "%s\n", binary_search(arr, len, 3) ? "true" : "false"
100
+
101
+ );
102
+
103
+ printf(
104
+
105
+ "%s\n", binary_search(arr, len, 10) ? "true" : "false"
106
+
107
+ );
108
+
109
+ }
110
+
111
+ ```
112
+
113
+
114
+
115
+ **実行結果** [Wandbox](https://wandbox.org/permlink/c4VTKKhFh0dHf5Xl)
116
+
117
+ ```
118
+
119
+ true
120
+
121
+ false
122
+
123
+ ```
124
+
125
+
126
+
127
+ OK。
128
+
129
+ たまたま上手くいっている可能性も捨てきれませんが、何もしないよりはマシです。
130
+
131
+
132
+
133
+ ######ステップ2: solve関数の前処理の実装と簡易なテスト
134
+
135
+ solve関数は、内部的にはいくつか処理に分かれています。
136
+
137
+ 0. データを成形する前処理
138
+
139
+ 0. サーチ
140
+
141
+ 0. 結果の出力
142
+
143
+
144
+
145
+ ここでは、まず前処理だけを実装します。
146
+
147
+ ```C++
148
+
149
+ void solve(int arr[], size_t len, int m)
150
+
151
+ {
152
+
153
+ int work[MAX_N * MAX_N];
154
+
155
+ size_t valid_len = len * len;
156
+
157
+
158
+
159
+ for(size_t i = 0; i < len; ++i) {
160
+
161
+ int offset = i * len;
162
+
163
+
164
+
165
+ for(size_t j = 0; j < len; ++j) {
166
+
167
+ work[offset + j] = arr[i] + arr[j];
168
+
169
+ }
170
+
171
+ }
172
+
173
+
174
+
175
+ std::sort(work, work + valid_len);
176
+
177
+
178
+
179
+ for(size_t i = 0; i < len; ++i) {
180
+
181
+ int offset = i * len;
182
+
183
+
184
+
185
+ for(size_t j = 0; j < len; ++j) {
186
+
187
+ printf("%2d ", work[offset + j]);
188
+
189
+ }
190
+
191
+ printf("\n");
192
+
193
+ }
194
+
195
+ }
196
+
197
+ ```
198
+
199
+
200
+
201
+ そしてダミーデータでチェック。
202
+
203
+ ```C++
204
+
205
+ int main(void) {
206
+
207
+ int arr[] = {1, 3, 5}; // できるだけ小規模に
208
+
209
+ size_t len = std::size(arr);
210
+
211
+
212
+
213
+ solve(arr, len, -1);
214
+
215
+ }
216
+
217
+ ```
218
+
219
+
220
+
221
+ **実行結果** [Wandbox](https://wandbox.org/permlink/JR621lVmwRpYjSHa)
222
+
223
+ ```
224
+
225
+ prog.cc: In function 'void solve(int*, size_t, int)':
226
+
227
+ prog.cc:32:39: warning: unused parameter 'm' [-Wunused-parameter]
228
+
229
+ void solve(int arr[], size_t len, int m)
230
+
231
+ ~~~~^
232
+
233
+ 2 4 4
234
+
235
+ 6 6 6
236
+
237
+ 8 8 10
238
+
239
+ ```
240
+
241
+
242
+
243
+ 問題なさそうです。
244
+
245
+
246
+
247
+ ######ステップ3: solve関数の本処理の実装と簡易なテスト
248
+
249
+ solve関数に機能を肉付けします。
250
+
251
+ ```C++
252
+
253
+ bool solve(int arr[], size_t len, int m)
254
+
255
+ //
256
+
257
+ // 前処理
258
+
259
+
260
+
261
+ ...
262
+
263
+
264
+
265
+
266
+
267
+ //
268
+
269
+ // 本処理
270
+
271
+
272
+
273
+ for(size_t i = 0; i < len; ++i) {
274
+
275
+ for(size_t j = 0; j < len; ++j) {
276
+
277
+
278
+
279
+ // 内側のループの代わりに2分探索
280
+
281
+ int purpose = m - arr[i] - arr[j];
282
+
283
+
284
+
285
+ if(binary_search(work, valid_len, purpose)) {
286
+
287
+ return true;
288
+
289
+ }
290
+
291
+ }
292
+
293
+ }
294
+
295
+
296
+
297
+ return false;
298
+
299
+ }
300
+
301
+ ```
302
+
303
+
304
+
305
+ そしてテスト。
306
+
307
+ ```C++
308
+
309
+ int main(void) {
310
+
311
+ {
312
+
313
+ int arr[] = {1, 3, 5};
314
+
315
+ size_t len = std::size(arr);
316
+
317
+
318
+
319
+ printf(
320
+
321
+ "%s\n", solve(arr, len, 10) ? "OK" : "NG"
322
+
323
+ );
324
+
325
+ }
326
+
327
+ {
328
+
329
+ int arr[] = {1, 3, 5};
330
+
331
+ size_t len = std::size(arr);
332
+
333
+
334
+
335
+ printf(
336
+
337
+ "%s\n", solve(arr, len, 9) ? "OK" : "NG"
338
+
339
+ );
340
+
341
+ }
342
+
343
+ }
344
+
345
+ ```
346
+
347
+
348
+
349
+ **実行結果** [Wandbox](https://wandbox.org/permlink/uCAE3w2hEHOG3Hfj)
350
+
351
+ ```
352
+
353
+ OK
354
+
355
+ NG
356
+
357
+ ```
358
+
359
+
360
+
361
+ ######ステップ4: 値を入力できるようにする
362
+
363
+ ここでようやく標準入力を利用します。
364
+
365
+ ```C++
366
+
367
+ int main(void) {
368
+
369
+ int arr[MAX_N];
370
+
371
+
372
+
373
+ size_t arr_len; scanf("%zu", &arr_len);
374
+
375
+ int purpose; scanf("%d", &purpose);
376
+
377
+
378
+
379
+ for(size_t i = 0; i < arr_len; ++i) {
380
+
381
+ scanf("%d", &arr[i]);
382
+
383
+ }
384
+
385
+
386
+
387
+ bool found = solve(arr, arr_len, purpose);
388
+
389
+ printf("%s\n", found ? "OK" : "NG");
390
+
391
+ }
392
+
393
+ ```
394
+
395
+
396
+
397
+ 完成。
398
+
399
+
400
+
401
+ コード
402
+
403
+ ---
404
+
405
+ ```C++
406
+
407
+ #include <cstdio>
408
+
409
+ #include <cstdlib>
410
+
411
+
412
+
413
+ #include <algorithm>
414
+
415
+
416
+
417
+
418
+
419
+ constexpr int MAX_N = 50;
420
+
421
+
422
+
423
+ bool binary_search(int sorted_arr[], size_t len, int purpose) {
424
+
425
+ int left = 0;
426
+
427
+ int right = len;
428
+
429
+
430
+
431
+ while (right - left >= 1) {
432
+
433
+ int middle = (left + right) / 2;
434
+
435
+
436
+
437
+ if (sorted_arr[middle] == purpose) {
438
+
439
+ return true;
440
+
441
+ }
442
+
443
+
444
+
445
+ if (sorted_arr[middle] < purpose) {
446
+
447
+ left = middle + 1;
448
+
449
+ }
450
+
451
+ else {
452
+
453
+ right = middle;
454
+
455
+ }
456
+
457
+ }
458
+
459
+
460
+
461
+ return false;
462
+
463
+ }
464
+
465
+
466
+
467
+ bool solve(int arr[], size_t len, int m)
468
+
469
+ {
470
+
471
+ //
472
+
473
+ // 前処理
474
+
475
+
476
+
477
+ int work[MAX_N * MAX_N];
478
+
479
+ size_t valid_len = len * len;
480
+
481
+
482
+
483
+ for(size_t i = 0; i < len; ++i) {
484
+
485
+ int offset = i * len;
486
+
487
+
488
+
489
+ for(size_t j = 0; j < len; ++j) {
490
+
491
+ work[offset + j] = arr[i] + arr[j];
492
+
493
+ }
494
+
495
+ }
496
+
497
+
498
+
499
+ std::sort(work, work + valid_len);
500
+
501
+
502
+
503
+ /*
504
+
505
+ for(size_t i = 0; i < len; ++i) {
506
+
507
+ int offset = i * len;
508
+
509
+
510
+
511
+ for(size_t j = 0; j < len; ++j) {
512
+
513
+ printf("%2d ", work[offset + j]);
514
+
515
+ }
516
+
517
+ printf("\n");
518
+
519
+ }
520
+
521
+ */
522
+
523
+
524
+
525
+
526
+
527
+ //
528
+
529
+ // 本処理
530
+
531
+
532
+
533
+ for(size_t i = 0; i < len; ++i) {
534
+
535
+ for(size_t j = 0; j < len; ++j) {
536
+
537
+
538
+
539
+ // 内側のループの代わりに2分探索
540
+
541
+ int purpose = m - arr[i] - arr[j];
542
+
543
+
544
+
545
+ if(binary_search(work, valid_len, purpose)) {
546
+
547
+ return true;
548
+
549
+ }
550
+
551
+ }
552
+
553
+ }
554
+
555
+
556
+
557
+ return false;
558
+
559
+ }
560
+
561
+
562
+
563
+ int main(void) {
564
+
565
+ int arr[MAX_N];
566
+
567
+
568
+
569
+ size_t arr_len; scanf("%zu", &arr_len);
570
+
571
+ int purpose; scanf("%d", &purpose);
572
+
573
+
574
+
575
+ for(size_t i = 0; i < arr_len; ++i) {
576
+
577
+ scanf("%d", &arr[i]);
578
+
579
+ }
580
+
581
+
582
+
583
+ bool found = solve(arr, arr_len, purpose);
584
+
585
+ printf("%s\n", found ? "OK" : "NG");
586
+
587
+ }
588
+
589
+ ```