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

回答編集履歴

5

妥当な文字列はtrueになるはずですよね

2018/06/20 16:23

投稿

miyabi-sun
miyabi-sun

スコア21461

answer CHANGED
@@ -91,7 +91,7 @@
91
91
  - `[[1, 2], [2, 3], [3, 4]]`
92
92
  - `[true, true, true]`
93
93
  - `3` ← trueが連続して続いたMax回数
94
- - `return 3 >= 2` ← 2回以上続いたらfalseを返す
94
+ - `return 3 < 2` ← 2回以上続いたらfalseを返す
95
95
 
96
96
  JavaScriptの全ての値はプロトタイプというメソッドがひっついています。
97
97
  質問文の`num.toString().split('')`はまさにそれで、JSの全ての型にはStringに変換する`toString`メソッドが用意されており、文字列に変換した後に`split`メソッドを利用して配列型に変換しています。
@@ -136,10 +136,10 @@
136
136
  .split('0') // ["111"]
137
137
  .map(it => it.length) // [3]
138
138
  .reduce((a, b) => Math.max(a, b), 0) // 3
139
- return maxLength >= 2;
139
+ return maxLength < 2;
140
140
  }
141
- checkNum(1235) // true
141
+ checkNum(1245) // true
142
- checkNum(1245) // false
142
+ checkNum(1235) // false
143
143
  ```
144
144
 
145
145
  そこそこ難解なので興味が出てきたらという感じで学習してみてください。

4

更に追記

2018/06/20 16:23

投稿

miyabi-sun
miyabi-sun

スコア21461

answer CHANGED
@@ -116,7 +116,8 @@
116
116
  ```
117
117
 
118
118
  では、早速データを加工していきましょう。
119
- 今回は連番している状態を1、連番ではない状態を2とします。
119
+ 今回は連番している状態を1、連番ではない状態を0として文字列変換を経由する事で実現させます。
120
+ 詳細は各行の末尾にどんな値に変換されるかをコメントで記載しました。
120
121
 
121
122
  ```JavaScript
122
123
  var isSerialNumber = (a, b) => {

3

おまけの解説を追加

2018/06/20 16:20

投稿

miyabi-sun
miyabi-sun

スコア21461

answer CHANGED
@@ -64,6 +64,9 @@
64
64
 
65
65
  おまけ: コードを洗練させていく
66
66
 
67
+ 引き出しのネタとして全く違うアプローチから解いていきます。
68
+ JavaScript中級者向けの内容となっていますので、分かる部分だけ持っていってください。
69
+
67
70
  AとBは連番であるというところを抜き出しましょうか
68
71
  シリアルナンバーと言えばなんか別のモノを指すように思えますが、まぁいいや、isシリアルナンバーという関数を用意します。
69
72
 
@@ -90,13 +93,16 @@
90
93
  - `3` ← trueが連続して続いたMax回数
91
94
  - `return 3 >= 2` ← 2回以上続いたらfalseを返す
92
95
 
93
- JavaScriptの配列中々優秀で、[map](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map)や[reduce](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)といったメソッドが用意されおり、
94
- 好きなよう加工するできます。
96
+ JavaScriptの全ての値プロトタイプといメソッドがひっついいます。
97
+ 質問文の`num.toString().split('')`はまさそれで、JSの全ての型にはStringに変換する`toString`メソッド用意されており、文字列に変換した後に`split`メソッドを利用して配列型に変換しています。
95
98
 
96
- これらのメソッドは関数を引数として要するので何度も関数定義必要になり、行数が増えがちなのですが、
99
+ に配列型には、[map](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map)や[reduce](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)といったメソッドが用意されおり、配列の各素を好きなように加工するができま
100
+
101
+ mapやreduceはメソッドは関数を引数として要求するので、何度も関数定義を書くことになり行数が増えがちなのですが、
97
102
  ES2015というバージョンで[アロー関数](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/arrow_functions)という書き方が使える様になりました。
98
103
  モダンブラウザではIE11以外のほぼ全てのブラウザで利用可能です。
99
104
  早速上記の連番判定関数をアロー関数で書き直してみます。
105
+ (functionが消えて`=>`という2文字の矢印を使ってるだけです、1行で値を返す場合は`{}`を省略出来たりと便利)
100
106
 
101
107
  ```JavaScript
102
108
  var isSerialNumber = (a, b) => {

2

おまけのコードが1行足りなかった

2018/06/20 16:14

投稿

miyabi-sun
miyabi-sun

スコア21461

answer CHANGED
@@ -126,7 +126,8 @@
126
126
  .map(it => isSerialNumber(it[0], it[1])) // [true, true, true]
127
127
  .map(it => it ? "1" : "0") // ["1", "1", "1"]
128
128
  .join('') // "111"
129
- .split('0') // [3]
129
+ .split('0') // ["111"]
130
+ .map(it => it.length) // [3]
130
131
  .reduce((a, b) => Math.max(a, b), 0) // 3
131
132
  return maxLength >= 2;
132
133
  }

1

エレガント方面に考えてみた

2018/06/20 16:06

投稿

miyabi-sun
miyabi-sun

スコア21461

answer CHANGED
@@ -29,10 +29,10 @@
29
29
  if (!last) {
30
30
  // 最初の文字を取得したら連番1とみなす
31
31
  count = 1;
32
- } else if (parseInt(it) == parseInt(last) + 1) {
32
+ } else if (parseInt(it) === parseInt(last) + 1) {
33
33
  // 取得文字が前回の文字より1多い場合、連番カウントを加算
34
34
  count++;
35
- } else if (last == '9' && it == 0) {
35
+ } else if (last === '9' && it === '0') {
36
36
  // 取得文字0、前回の文字9の場合は連番とみなしてカウントを加算
37
37
  count++;
38
38
  } else {
@@ -58,4 +58,83 @@
58
58
  ```
59
59
 
60
60
  質問文から素直にコードにするとこんな感じのところがゴールになります。
61
- もう少し発展させてエレガントなコードにするとkeiさんのコードになるでしょう。
61
+ もう少し発展させてエレガントなコードにするとkeiさんのコードになるでしょう。
62
+
63
+ ---
64
+
65
+ おまけ: コードを洗練させていく
66
+
67
+ AとBは連番であるというところを抜き出しましょうか
68
+ シリアルナンバーと言えばなんか別のモノを指すように思えますが、まぁいいや、isシリアルナンバーという関数を用意します。
69
+
70
+ ```JavaScript
71
+ function isSerialNumber (a, b) {
72
+ if (a === 9 && b === 0) return true;
73
+ if (b === a + 1) return true;
74
+ return false;
75
+ }
76
+ isSerialNumber(1, 2) // true
77
+ isSerialNumber(9, 0) // true
78
+ isSerialNumber(1, 3) // false
79
+ ```
80
+
81
+ 続いて、`1234`という数字列の判定をしていきます。
82
+ これは左の数字と、右の数字が連結…つまり`1と2`、`2と3``3と4`文字目の連結を確認して、
83
+ 2つの連結が同時に起こっている場合は3文字連番が続いているので不正と判断出来ます。
84
+
85
+ 従って下記のような順序でデータを加工できれば判別が可能となります。
86
+
87
+ - `["1", "2", "3", "4"]`
88
+ - `[[1, 2], [2, 3], [3, 4]]`
89
+ - `[true, true, true]`
90
+ - `3` ← trueが連続して続いたMax回数
91
+ - `return 3 >= 2` ← 2回以上続いたらfalseを返す
92
+
93
+ JavaScriptの配列は中々優秀で、[map](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map)や[reduce](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)といったメソッドが用意されており、
94
+ 好きなように加工する事ができます。
95
+
96
+ これらのメソッドは関数を引数として要求するので何度も関数定義が必要になり、行数が増えがちなのですが、
97
+ ES2015というバージョンで[アロー関数](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/arrow_functions)という書き方が使える様になりました。
98
+ モダンブラウザではIE11以外のほぼ全てのブラウザで利用可能です。
99
+ 早速上記の連番判定関数をアロー関数で書き直してみます。
100
+
101
+ ```JavaScript
102
+ var isSerialNumber = (a, b) => {
103
+ if (a === 9 && b === 0) return true;
104
+ if (b === a + 1) return true;
105
+ return false;
106
+ }
107
+ isSerialNumber(1, 2) // true
108
+ isSerialNumber(9, 0) // true
109
+ isSerialNumber(1, 3) // false
110
+ ```
111
+
112
+ では、早速データを加工していきましょう。
113
+ 今回は連番している状態を1、連番ではない状態を2とします。
114
+
115
+ ```JavaScript
116
+ var isSerialNumber = (a, b) => {
117
+ if (a === 9 && b === 0) return true;
118
+ if (b === a + 1) return true;
119
+ return false;
120
+ }
121
+ function checkNum(num){
122
+ var arr = num.toString().split('') // ["1", "2", "3", "4"]
123
+ var maxLength = arr
124
+ .map((it, i) => i === 0 ? null : [parseInt(arr[i - 1]), parseInt(it)]) // [null, [1, 2], [2, 3], [3, 4]]
125
+ .slice(1) // [[1, 2], [2, 3], [3, 4]]
126
+ .map(it => isSerialNumber(it[0], it[1])) // [true, true, true]
127
+ .map(it => it ? "1" : "0") // ["1", "1", "1"]
128
+ .join('') // "111"
129
+ .split('0') // [3]
130
+ .reduce((a, b) => Math.max(a, b), 0) // 3
131
+ return maxLength >= 2;
132
+ }
133
+ checkNum(1235) // true
134
+ checkNum(1245) // false
135
+ ```
136
+
137
+ そこそこ難解なので興味が出てきたらという感じで学習してみてください。
138
+
139
+ メソッドチェインを覚えるとこんな感じで値を転がしていけるようになるので慣れたら楽です。
140
+ 最初はとっつきにくいと思いますので、1行ずつ実行していってみてください。