回答編集履歴

1

バグ修正(追記)

2016/09/27 09:36

投稿

退会済みユーザー
answer CHANGED
@@ -47,4 +47,75 @@
47
47
  System.out.println(check(new int[] {0,2,2,0,1,3,1,1,0,4,0}));
48
48
  }
49
49
  }
50
- ```
50
+ ```
51
+
52
+ ###バグ修正(追記)
53
+ バグを修正しました。仕様をよく読んでいなかったのが原因。
54
+
55
+ その前に、Bertrand Meyerの「契約による設計」に従い、事前条件チェックをちゃんとやります。
56
+
57
+ ```Java
58
+ if (args == null && args.length != 11) {
59
+ throw new IllegalArgumentException();
60
+ }
61
+ if (args[0] != 0 || args[10] != 0) {
62
+ throw new IllegalArgumentException();
63
+ }
64
+ ```
65
+
66
+ 数列の積を使ってパターンを判定するようにしました。
67
+
68
+ ```Java
69
+ static int check(int[] args) {
70
+
71
+ for (int i=0, cnt=0, prod=1, pos=-1; i<11; ++i) {
72
+ int value = args[i];
73
+ if (value == 0) {
74
+ if (cnt == 4) {
75
+ return pos;
76
+ }
77
+ cnt = 0;
78
+ prod = 1;
79
+ } else {
80
+ prod *= value;
81
+ cnt += (value == 2 && prod == 4) ? 11 : value;
82
+ pos = ((value == 2 || value == 4) ||
83
+ prod == 1 || (prod == 3 && value == 1)) ? i : pos;
84
+ }
85
+ }
86
+ return -1;
87
+
88
+ }
89
+ ```
90
+ このコードが良くないのは、強引なやり方をしていてよく分からないことと、仕様変更に弱いことです。
91
+
92
+ 正規表現を使う方が、仕様変更に強い(正規表現だけを変えれば良い)し、わかりやすいと思いましたので、掲載します。
93
+
94
+ ```Java
95
+
96
+ static final String SEQ_PATTERN =
97
+ "^.*0111(1)0|011(2)0|01(2)10|0(2)110|0(1)30|03(1)0|0(4)0.*$";
98
+
99
+ static int check(int[] args) {
100
+
101
+ StringBuilder buff = Arrays
102
+ .stream(args)
103
+ .collect(
104
+ StringBuilder::new,
105
+ (b,v) -> b.append(String.valueOf(v)),
106
+ (c,d) -> c.append(d)
107
+ );
108
+ String seq = new String(buff);
109
+ Matcher m = Pattern.compile(SEQ_PATTERN).matcher(seq);
110
+ if (m.find()) {
111
+ for (int i=1; i<=m.groupCount(); ++i) {
112
+ if (m.group(i) != null) {
113
+ return m.start(i);
114
+ }
115
+ }
116
+ }
117
+ return -1;
118
+ }
119
+
120
+ ```
121
+ 正規表現の書き方が悪いとか、ストリームAPIの使い方がよくないと思っています。しかし、仕様変更があってもコードを変更しなくても良いところが気に入っています。