LoginSignup
2
0

More than 3 years have passed since last update.

AtCoderの入力例を一度に試すための1行(Ruby)

Last updated at Posted at 2020-03-15

AtCoder等のプログラミング問題を解く際、提出前に手元の環境で動作確認すると思う。私の場合は便利な環境を用意できていなく1、代わりに paiza.io を利用している2

問題には入出力の例が複数与えられているのでなるべく全て試したいが、入力例をいちいち変えるのが辛い。自分で例を追加する場合は尚更である。

環境を整えてさえいれば、テストの自動生成なども可能なようだが…

RubyでAtcoderからテストを自動生成するライブラリを作りました - Qiita

何とかならないか考えた結果、Rubyにおいて1行で解決する方法を思いついた。

方法

Rubyスクリプトの最後に以下の1行を追加する。解答のメソッド化などは必要ない。

load __FILE__ unless $stdin.eof?

あとは入力例を結合して読み込ませれば、全ての出力がまとめて表示される。

【追記】
スクリプト内で exit を使う可能性を考慮したより汎用的な方法。Rubyスクリプトの先頭のほう(必ず実行される場所)に以下の1行を追加する。

END { load __FILE__ unless $stdin.eof? }

制限

解答のスクリプト内では「入力終端まで読み込む」ことをしてはいけない。問題に与えられた数字をもとに #gets などで正確な行数だけ取得しなければいけない。

動作原理

単に同じスクリプトを何度も実行している。

Kernel.#loadKernel.#require と異なり、常に指定ファイルを読み込む。指定ファイルとして自分自身を与えれば、スクリプトを再び先頭から実行する効果が得られる。あとは無限ループ防止のために「入力終端でなければ」という条件を追加すればいい。

【追記】
END を使った方法はRubyの終了処理の仕組みを利用している。「同じスクリプトの実行」を終了処理の一環として登録することで、スクリプトの途中で終える場合でも動作する。

AtCoder Beginner Contest 154 の A問題 に適用してみる。この問題は入力が3行で与えられる。

abc154_a.rb
s, t = gets.split
a, b = gets.split.map(&:to_i)
u    = gets.chomp

if u == s
  a -= 1
else
  b -= 1
end

puts "#{a} #{b}"

load __FILE__ unless $stdin.eof?

入力例が2つあるので、それらを結合して与える。

入力例1,2
red blue
3 4
red
red blue
5 5
blue

すると、それぞれの結果がまとめて表示される。

出力
2 4
5 4

制限に違反した場合

解答のスクリプト内で「入力終端まで読み込む」ことをしてしまうと、一度に試すことはできなくなる。提出する分には問題ない。

abc154_a.rb
s, t, *ab, u = $stdin.read.split
ab.map!(&:to_i)
ab[u == s ? 0 : 1] -= 1
puts ab * " "

load __FILE__ unless $stdin.eof?
出力
3 3 0 0 0 5 5

  1. 電車の中からタブレットで参加することもあった 

  2. 言語のバージョンを合わせられないのでお勧めはしない 

2
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
2
0