LoginSignup
0
0

More than 3 years have passed since last update.

Atcoderをjavascriptでやる時、入力値をイテレータ(反復)型として操作できるテンプレを作ってみた

Posted at

目的

入力値の受け取りを単一文字列 → 改行分割した配列に置き換わることによってコーディング効率を少し上げる。
次のようなメリットを利用できる。
・改行分割のコーディングがいらなくなる
・「要素数」と「要素一覧」を切り分けやすくなる

GoF提唱のデザインパターン:イテレータを適用したつもり。

テンプレート

template.js
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

anti1.js
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(" ");
  //配列番号指定がマジックナンバー。指定ミスが起こりやすい
}
ref1.js
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

anti2-1.js
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の追加が合ってるか不安 )
}
anti2-2.js
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();
  }
  //「常に一番上をとる」ということで各所にシフトが必要。
}
ref2.js
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()に任せて取っていける
}

終わりに

配列を使うことが前提となる問題では、配列で扱えるよう下準備をしておく必要がある。
問題に当たるたびに相応のコーディングをしなければならないが、割と時間を食っていた。
毎回やるの嫌だったので作ってみたよというだけの話。

ちなみにCodeforcesではnext()をreadline()に書き換えるだけでOK(V8が同種の処理を持ってる)

Javaにも同種のふるまいをするクラス(java.util.Iterator)があり、そこではremove()がある。これ要る?

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0