Ruby paizaの標準入力値取得・出力サンプルコード

最低限の標準入力値取得ができるようになったので、paizaプログラミングスキルチェックの値取得・サンプルコードで、実際に標準入力値の取得と出力ができるか試してみました。

paiza.jp

paizaサンプルコード

入力される値

2
2 5
3 4

このテストケースでは、最初の値は、その後入力される行数を示す(2行の入力がある) 2行目以降は、helloとworldの値が[,]区切りで書かれています。

期待する出力

hello = 2 , world = 5
hello = 3 , world = 4

実際にやってみる

3行の入力値を取得するだけならgetsを3回書けばよいはずですが、問題をよく読むと、

最初の値は、その後入力される行数を示す(2行の入力がある)

と、なかなか意味ありげなことが書いてあります。

つまり、最初の行の値を取得した上で、それを利用して以降の行を取得しなければいけないようです。

実は自分もこういうのはRubyでは初めてなので自信がありませんが、やってみます。

n行の入力値を取得するには?

1行目は行数なので、受け取った値を整数に変換するだけでいいと思います。

n = gets.to_i

問題はここからです。 標準入力を受け取るgetsn回繰り返すには、どう書けばいいのでしょうか。

とりあえず、取得する値が2つあるとか数値だとかいうことは置いておいて、とにかくngetsして、受け取った値を 処理できるようにすることを最初の目標にします。

繰り返すメソッドといえば、timeswhileぐらいしか思いつきません。

取得値を空の配列に入れていく

空の配列を作って、そこに取得した値を入れていく方法を考えてみました。

n = gets.to_i
ary = []  #空の配列を作る
n.times { ary << gets.chomp }  #配列aryの末尾に受け取った値を要素として追加

p ary #=> ["2 5", "3 4"]

一応取得することはできました。nが違う値に変わっても対応できそうです。ただ、これだと1行が1つの要素になっているので、出力する処理がややこしくなります。

これは正解ではなさそうだということで、次は、文字列をスペース区切りで分割できるsplitを一緒に使ってみます。

n = gets.to_i
ary = []
n.times { ary << gets.chomp.split }

p ary #=> [["2", "5"], ["3", "4"]]

分割できました!…が、1行で1つの配列ができて、配列の配列になってしまいました。

これも正解ではない気がしてきましたが、これで「期待する出力」ができるのか試しにやってみます。

n = gets.to_i
ary = []
n.times { ary << gets.chomp.split }

puts "hello = #{ary[0][0]}, world = #{ary[0][1]}" #=> hello = 2, world = 5
puts "hello = #{ary[1][0]}, world = #{ary[1][1]}" #=> hello = 3, world = 4

できました!期待する出力と同じ結果です。

が、これだと最後のputsを、n行分自分で書かないといけなくなり、nが2以外の値になったときに対応できません。そして何より、コードが重複していてかっこ悪い。

うーん、putsの行は2行、つまりn行…

ということは、繰り返しのtimesメソッドの中に入れられるのでは!!

完成したコード

結果、こうなりました。

n = gets.to_i
n.times do  #以下をn回繰り返す
    ary = gets.chomp.split  #取得値をスペース区切りで分割し配列aryに要素として追加
    puts "hello = #{ary[0]}, world = #{ary[1]}"  #出力
end

#=> hello = 2, world = 5
#=> hello = 3, world = 4

大分遠回りしましたが、自分の答えができたところで、解答例を見てみることにします。

解答例との比較

サンプルコード:Ruby

input_line = gets.to_i
input_line.times do
  s = gets.chomp.split(" ")
  print "hello = #{s[0]} , world = #{s[1]}\n"
end

ほぼ同じですね。変数名以外で違うところは、splitの引数の有無と、出力がputsprintかという点です。

splitの引数

文字列を区切り文字で分割して配列にするsplitは、split(":")のように引数を入れればその文字(この例ではコロン:)で分割できますが、引数を省略するとスペース空白文字で分割します。なので、今回の場合は引数を省略できます。

ちなみに、この例ではchompはなくても OK でした。

masuyama13.hatenablog.com

putsprintの違い

putsprintの違いは、最後に改行が入るか入らないかです。paizaのスキルチェックの解答(出力結果)は、最後に改行を入れることになっているので、いつもputsを使っています。printを使う場合は、サンプルコードのように改行文字\nを入れる必要があります。

つまり、puts "hello"と print "hello\n"は同じで、サンプルコードと自分の答えも同じということになります。