本記事はpaizaの利用規約 第8条 10項に抵触していないと考えていますが、万が一指摘があれば本記事は削除します。
第8条(禁止事項)
10.ブログ・SNS等本サイト以外の媒体(インターネット媒体に限られず、不特定多数が閲覧可能なものを全て含む。)上において、当社が出題した問題の内容、当該問題に対する解答、解答へのヒント等の示唆及びカンニング等の不正を助長する内容等を掲載する行為。
はじめに
度々面白いオンラインハッカソン(?)をやってくれる paiza ですが、可愛い女の子につられてやってみた人も多いんじゃないかと思います。(かくいう私がそうですが)
paizaの問題のほとんどは標準入力から何らかのデータを受け取り、解答を標準出力に出すという形式です。全問題を見たわけではありませんが、私が今まで解いた問題は全てその形式だったと思います。
コードを書くにはブラウザ上のエディタも一応提供されていますが、やはり普段使っている環境で書きたいことがあると思います。そこで、ローカル環境で動作確認を行う際に使える小ワザを書いてみます。タイトルにも入れていますがRubyで使える小ワザです。
本題
標準入力(gets
), 標準出力(puts
)を使うコードをテストするのは面倒だなーと思い、Kernel.gets
, Kernel.puts
が呼ばれないように、自分で gets
, puts
を作ってみました。
たとえば、「n回、数値が与えられるのでそれぞれ2倍にした数値を出しなさい。(最初にnが与えられ、以降は数値がn回与えられる)」という問題の場合。(これは私が作った架空の問題です)
具体的には、以下のような感じです。
NL = "\n"
INPUT = 0
OUTPUT = 1
@data = [ # 問題文で入力例と出力例が1〜3個ほど例示されるので、それをコピって貼り付ける
[ # 例-1
<<EOS, ## 入力例-1
1
2
EOS
<<EOS ## 出力例-1
4
EOS
],
[ # (問題文で与えられれば)例-2
<<EOS, ## 入力例-2
2
1
5
EOS
<<EOS ## 出力例-2
2
10
EOS
]
].map { |entry| [entry[INPUT].split(NL), entry[1]] } # 1行ずつ読むように改行で分割して配列にする
@i = -1
def gets
@data[@test_case - 1][INPUT][@i += 1] + NL
end
@output = ""
def puts(content)
@output << content.to_s + NL
end
def assert
return Kernel.puts "OK!" if @data[@test_case - 1][OUTPUT] == @output
Kernel.puts "NG!!!",
"expected: ", @data[@test_case - 1][OUTPUT],
"actual: ", @output
end
# 実行したいテストケースを指定する
@test_case = 1
### 提出コード ここから ###
gets.to_i.times { puts gets.to_i * 2 }
### 提出コード ここまで ###
# 動作が正しいかチェック
assert
正解の場合の出力例:
OK!
不正解の場合の出力例:
NG!!!
expected:
2
10
actual:
3
15
注意点
- 結構な数のインスタンス変数を使っているので、解答コードで変数名が重複しないように気をつける
- プリントデバッグしたい場合など、
puts
そのままでは使えないのでKernel.puts
と書くかp
等を使う
--
テスト書くならminitestなりrspecなり使えばええやん、という意見もあるかと思いますが、問題には制限時間もあるため簡便な方法が好みです。また、きっちりやるならば ARGV
や ARGF
を使ったり、テスト用コード部分は別ファイルにしてrequireするなど色々あるかと思いますが、まぁこんな感じということで。
他にも小ワザ等あれば教えてください。