目的
入力値の受け取りを単一文字列 → 改行分割した配列に置き換わることによってコーディング効率を少し上げる。
次のようなメリットを利用できる。
・改行分割のコーディングがいらなくなる
・「要素数」と「要素一覧」を切り分けやすくなる
GoF提唱のデザインパターン:イテレータを適用したつもり。
テンプレート
var input = require("fs").readFileSync("/dev/stdin", "utf8").trim().split("\n");
var obj = {
"list" : input,
"index" : 0,
"max" : input.length,
"next" : function(){
if(!this.hasNext()){return null;}
var returnObj = this.list[this.index];
this.index++;
return returnObj;
},
"hasNext" : function(){return (this.index < this.max);}
}
function next(){return obj.next();}
function hasNext(){return obj.hasNext();}
function Main(){
//ここに処理入れてく
}
Main();
アンチパターンとリファクタリング結果
アンチパターンの方は、最初に下記コードがあるとする。
var input = require("fs").readFileSync("/dev/stdin", "utf8").trim();
例1:1行=1数列の場合
N
A1 A2 A3 A4 ... AN
B1 B2 B3 B4 ... BN
C1 C2 C3 C4 ... CN
function Main(){
input = input.split("\n");
var N = parseInt(input[0]);
var aList = input[1].split(" ");
var bList = input[2].split(" ").map((a)=>Number(a));//数値型へ変換
var cList = input[3].split(" ");
//配列番号指定がマジックナンバー。指定ミスが起こりやすい
}
function Main(){
var N = parseInt(next());
var aList = next().split(" ");
var bList = next().split(" ").map((a)=>Number(a));//数値型へ変換
var cList = next().split(" ");
//すべてnext()に置き換えられる
}
例2:N行=1数値の場合
N
A1
A2
...
AN
Q
B1
B2
...
BQ
function Main(){
input = input.split("\n");
var N = parseInt(input[0]);
var aList = new Array(N);
for(var i = 1; i <= N; i++){
aList[i - 1] = parseInt(input[i]);
}
var Q = parseInt(input[N + 1]);
var bList = new Array(Q);
for(var i = 0; i < Q; i++){
bList[i] = parseInt(input[N + i + 2]);
}
//追加先と追加元のインデックスがずれてめんどくさい( 特にbListの追加が合ってるか不安 )
}
function Main(){
input = input.split("\n");
var N = parseInt(input[0]);
input.shift();
var aList = new Array(N);
for(var i = 0; i < N; i++){
aList[i] = parseInt(input[0]);
input.shift();
}
var Q = parseInt(input[0]);
input.shift();
var bList = new Array(Q);
for(var i = 0; i < Q; i++){
bList[i] = parseInt(input[0]);
input.shift();
}
//「常に一番上をとる」ということで各所にシフトが必要。
}
function Main(){
var N = parseInt(next());
var aList = new Array(N);
for(var i = 0; i < N; i++){
aList[i] = parseInt(next());
}
var Q = parseInt(next());
var bList = new Array(Q);
for(var i = 0; i < Q; i++){
bList[i] = parseInt(next());
}
//最初に取るのが「要素の大きさ」であることを前提とすれば
//あとはnext()に任せて取っていける
}
終わりに
Atcoderのコンテストにjavascriptで参加すると、入力値が単一文字列として取得できる。
— 便利屋(仮)わたりさん🖥🏍 (@watarimaycry2) January 19, 2020
その後、目的に合わせて色々やらないといけない。それだけで毎回30秒~1分ほど時間食ってることに悶々してた。
なので1行ずつ取り出せるように最適化してみたよ pic.twitter.com/aSeoW9A0lF
配列を使うことが前提となる問題では、配列で扱えるよう下準備をしておく必要がある。
問題に当たるたびに相応のコーディングをしなければならないが、割と時間を食っていた。
毎回やるの嫌だったので作ってみたよというだけの話。
ちなみにCodeforcesではnext()をreadline()に書き換えるだけでOK(V8が同種の処理を持ってる)
Javaにも同種のふるまいをするクラス(java.util.Iterator)があり、そこではremove()がある。これ要る?