Ruby プログラミング

[Ruby] 標準出力(データを任意に整形して出力する)

stdout

こんにちは!じゃいごテックのあつしです。

paizaなどの競技プログラミングでは標準入力でデータ受け取って、標準出力で処理結果を回答します。
Rubyにはいくつか標準出力メソッドが用意されていますが、当ブログでは基本的にpメソッド・putsメソッドを使って解説していきます。

標準入力とは

実行されているプログラムがデータを受け取る入力元のことです。キーボードやファイルからのデータ入力と思っておけばOK!
文字列で渡されるので、数値として扱うには文字列型から数値型への変更が必要です。

標準出力とは

プログラム処理結果の出力先のことです。画面表示と思っておけばOK!

標準出力メソッド

putsメソッド

puts(オブジェクト)

文字列を渡すと与えられた文字列と改行を出力します。末尾に改行がなければ改行を加えます。

# 末尾に改行があればそのまま出力する
puts "JAIGO TEC\n"
# > JAIGO TEC

puts "JAIGO\nTEC\n\n"
# > JAIGO
# > TEC
# >

# 末尾に改行がなければ改行を追加して出力する
puts "JAIGO TEC"
# > JAIGO TEC

配列を渡すと、平坦化して先頭からその要素と改行を出力します。

# 配列を渡すと先頭から出力する
puts ["abc", "def", "ghi"]
# > abc
# > def
# > hij

# 配列を平坦化して出力する
# [["jkl", "mno"], "pqr", ["stu", "vwx"]] -> ["jkl", "mno", "pqr", "stu", "vwx"]
puts [["jkl", "mno"], "pqr", ["stu", "vwx"]]
# > jkl
# > mno
# > pqr
# > stu
# > vwx

文字列以外のオブジェクトを渡すと、to_a, to_sで出力できる形式への変換を試みます。

puts 123
# > 123

puts Math::PI
# > 3.141592653589793

puts Float::INFINITY
# > Infinity

puts 10e6
# > 10000000.0

puts Time.now
# > 2021-08-24 11:50:41 +0900

nil, "" を渡すと改行のみ出力します。

puts nil
# >

puts ""
# >

pメソッド

p(オブジェクト)

引数を人間に読みやすい形に整形して出力します。主にデバッグで使用します。

# 文字列と改行を出力する
p "JAIGO TEC\n"
# > "JAIGO TEC\n"

p "JAIGO\nTEC\n\n"
# > "JAIGO\nTEC\n\n"

p "JAIGO TEC"
# > "JAIGO TEC"

# nil, "" を出力する
p nil
# > nil

p ""
# > ""

# 配列を出力する
p ["abc", "def", "ghi"]
# > ["abc", "def", "ghi"]

p [["jkl", "mno"], "pqr", ["stu", "vwx"]]
# > [["jkl", "mno"], "pqr", ["stu", "vwx"]]

# 文字列以外のオブジェクトを出力する
p 123
# > 123

p Math::PI
# > 3.141592653589793

p Float::INFINITY
# > Infinity

p 10e6
# > 10000000.0

p Time.now
# > 2021-08-24 13:14:06.8991634 +0900

出力する文字列を整形する

文字列を +<< で連結して出力形式を整えても良いのですが、数値型も含まれていると、to_sメソッドで変換する必要があります。
Rubyには式展開という便利な機能がありますのでご紹介します。

式展開

#{オブジェクト}

文字列の中に変数や式を埋め込んで展開することが出来ます。to_sで文字列に変換してくれるので文字列以外も使うことが出来ます。
式展開する文字列はダブルクォート""で囲む必要があります。

first_name = "Taro"
last_name = "Yamada"
age = 20

# + を使う
puts "name: " + first_name + " " + last_name + " age: " + age.to_s
# > name: Taro Yamada age: 20

# << を使う (+ より処理が早い)
puts "name: " << first_name << " " << last_name << " age: " << age.to_s
# > name: Taro Yamada age: 20

# 式展開を使う
puts "name: #{first_name} #{last_name} age: #{age}"
# > name: Taro Yamada age: 20

# シングルクォートだとそのまま出力される
puts 'name: #{first_name} #{last_name} age: #{age}'
# > name: #{first_name} #{last_name} age: #{age}

# #{}の中で式やメソッドを使うことが出来る
puts "name: #{first_name.upcase} #{last_name.upcase} age: #{age + 5}"
# > name: TARO YAMADA age: 25

# ヒアドキュメントでも使うことが出来る
puts <<~"TEXT"
  **************************
  name: #{first_name} #{last_name} age: #{age}
  **************************
TEXT
# > **************************
# > name: Taro Yamada age: 20
# > **************************
文字列の左寄せ・右寄せ・中央寄せ

対象文字列.ljust(文字数, [padding = "埋める文字"])
対象文字列.rjust(文字数, [padding = "埋める文字"])
対象文字列.center(文字数, [padding = "埋める文字"])

対象文字列を文字数に左寄せ・右寄せ・中央寄せして、空いたスペースをpaddingで埋めた文字列を返します。
対象文字列の方が文字数が多い場合は対象文字列のコピーを返し、paddingを省略した場合は半角スペースで埋めます。

p "apple".ljust(4)
p "apple".ljust(5)
p "apple".ljust(6)
p "apple".ljust(7)
p "apple".ljust(8)
p "apple".ljust(9)
p "apple".ljust(9, "*")
# > "apple"
# > "apple"
# > "apple "
# > "apple  "
# > "apple   "
# > "apple    "
# > "apple****"

p "apple".rjust(4)
p "apple".rjust(5)
p "apple".rjust(6)
p "apple".rjust(7)
p "apple".rjust(8)
p "apple".rjust(9)
p "apple".rjust(9, "*")
# > "apple"
# > "apple"
# > " apple"
# > "  apple"
# > "   apple"
# > "    apple"
# > "****apple"

p "apple".center(4)
p "apple".center(5)
p "apple".center(6)
p "apple".center(7)
p "apple".center(8)
p "apple".center(9)
p "apple".center(9, "*")
# > "apple"
# > "apple"
# > "apple "
# > " apple "
# > " apple  "
# > "  apple  "
# > "**apple**"
数値型の右寄せ・0埋め

"%0桁数d" % 整数
"%0桁数.小数点以下桁数f" % 浮動小数点

整数型の場合は %d、 浮動小数点型の場合は %f を使います。桁数指定の前の0を省略すると、半角スペースで文字埋めします。

# 整数型を0埋めの文字列にしたものを生成
p "%03d" % 123
p "%04d" % 123
p "%05d" % 123
p "%06d" % 123
# 0を削除すると半角スペースで埋める
p "%7d" % 123
# > "123"
# > "0123"
# > "00123"
# > "000123"
# > "   123"

# 浮動小数点型を0埋めの文字列にしたものを生成
p "%08.0f" % 12.345
p "%08.1f" % 12.345
p "%08.2f" % 12.345
p "%08.3f" % 12.345
p "%08.4f" % 12.345
# 0を削除すると半角スペースで埋める
p "%8.4f" % 12.345
# > "00000012"
# > "000012.3"
# > "00012.34"
# > "0012.345"
# > "012.3450"
# > " 12.3450"
九九の表を作ってみる

式展開と整数型の右寄せを使って九九の表を作ってみます。

(1..9).each do |a|
  line = ""
  (1..9).each do |b|
    line << "#{a}×#{b}=#{"%2d" % (a * b)}"
    break if b == 9
    line << ", "
  end
  puts line
end

# > 1×1= 1, 1×2= 2, 1×3= 3, 1×4= 4, 1×5= 5, 1×6= 6, 1×7= 7, 1×8= 8, 1×9= 9
# > 2×1= 2, 2×2= 4, 2×3= 6, 2×4= 8, 2×5=10, 2×6=12, 2×7=14, 2×8=16, 2×9=18
# > 3×1= 3, 3×2= 6, 3×3= 9, 3×4=12, 3×5=15, 3×6=18, 3×7=21, 3×8=24, 3×9=27
# > 4×1= 4, 4×2= 8, 4×3=12, 4×4=16, 4×5=20, 4×6=24, 4×7=28, 4×8=32, 4×9=36
# > 5×1= 5, 5×2=10, 5×3=15, 5×4=20, 5×5=25, 5×6=30, 5×7=35, 5×8=40, 5×9=45
# > 6×1= 6, 6×2=12, 6×3=18, 6×4=24, 6×5=30, 6×6=36, 6×7=42, 6×8=48, 6×9=54
# > 7×1= 7, 7×2=14, 7×3=21, 7×4=28, 7×5=35, 7×6=42, 7×7=49, 7×8=56, 7×9=63
# > 8×1= 8, 8×2=16, 8×3=24, 8×4=32, 8×5=40, 8×6=48, 8×7=56, 8×8=64, 8×9=72
# > 9×1= 9, 9×2=18, 9×3=27, 9×4=36, 9×5=45, 9×6=54, 9×7=63, 9×8=72, 9×9=81

配列の要素を結合して文字列を整形する

配列を任意の文字列で結合するにはjoinメソッドを使用します。

joinメソッド

配列.join("結合文字列")

配列を平坦化して分割文字列で結合した文字列を返します。to_sで文字列に変換してくれるので文字列以外も使うことが出来ます。

# 文字列要素の配列
p ["apple", "banana", "cherry"].join(" ")
# > "apple banana cherry"

# 整数の配列
p [150, 100, 300].join(" ")
# > "150 100 300"

# 文字列と数値が混在してもOK, 多次元配列でもOK
p [["apple", 150], "banana", 100, ["cherry", 300]].join(",")
# > "apple,150,banana,100,cherry,300"
九九の表を作ってみる2

式展開と整数型の右寄せとjoinメソッド使って九九の表を作ってみます。

(1..9).each do |a|
  line = []
  (1..9).each do |b|
    line << "#{a}×#{b}=#{"%2d" % (a * b)}"
  end
  puts line.join(", ")
end

# > 1×1= 1, 1×2= 2, 1×3= 3, 1×4= 4, 1×5= 5, 1×6= 6, 1×7= 7, 1×8= 8, 1×9= 9
# > 2×1= 2, 2×2= 4, 2×3= 6, 2×4= 8, 2×5=10, 2×6=12, 2×7=14, 2×8=16, 2×9=18
# > 3×1= 3, 3×2= 6, 3×3= 9, 3×4=12, 3×5=15, 3×6=18, 3×7=21, 3×8=24, 3×9=27
# > 4×1= 4, 4×2= 8, 4×3=12, 4×4=16, 4×5=20, 4×6=24, 4×7=28, 4×8=32, 4×9=36
# > 5×1= 5, 5×2=10, 5×3=15, 5×4=20, 5×5=25, 5×6=30, 5×7=35, 5×8=40, 5×9=45
# > 6×1= 6, 6×2=12, 6×3=18, 6×4=24, 6×5=30, 6×6=36, 6×7=42, 6×8=48, 6×9=54
# > 7×1= 7, 7×2=14, 7×3=21, 7×4=28, 7×5=35, 7×6=42, 7×7=49, 7×8=56, 7×9=63
# > 8×1= 8, 8×2=16, 8×3=24, 8×4=32, 8×5=40, 8×6=48, 8×7=56, 8×8=64, 8×9=72
# > 9×1= 9, 9×2=18, 9×3=27, 9×4=36, 9×5=45, 9×6=54, 9×7=63, 9×8=72, 9×9=81

今回のまとめ

paizaスキルチェックで出題されそうな標準出力のパターンを一通り紹介しました。
中でも式展開joinメソッドは特によく使いますので是非覚えて使ってみて下さい。

式展開やjoinメソッドを使うと出力の形式をスマートに表現できるのが良いですよね。

【PR】Ruby学習でお世話になった本




【PR】アルゴリズム学習でお世話になった本


アルゴリズム関連の技術書は大抵C/C++で書かれていますが、ある程度プログラムが出来れば、処理の流れは理解することが出来ます。






通称: 螺旋本。C++で解説されています。AOJ(Aizu Online Judge)を運営している会津大学の渡辺准教授が書いた本です。データ構造や計算量の内容から丁寧に書いてありますのでアルゴリズム学習の最初の参考書としてオススメです。







通称: 蟻本。C++で解説されています。競技プログラミング中級者の定番書と言われていて、競技プログラミングで利用できる色々なアルゴリズムを学ぶことが出来ます。かなり高度な内容も含まれているので1冊分を完全に理解するのにはかなりの時間がかかりそうですが、手元に置いて何度も読み返しています。







通称: チーター本。C#, C++, JAVAでTopcoderの問題を解説しています。初心者~中級者向けに書かれているので解説が非常に丁寧です。







Python3でアルゴリズムを解説している本です。講義スタイルの本で、図やフローチャートを使ってアルゴリズムとデータ構造についてしっかりと説明されています。代わりにコードは少なめです。Pythonコードが読めなくても十分理解できると思います。


-Ruby, プログラミング
-,

© 2024 じゃいごテック