こんにちは!じゃいごテックのあつしです。
今回はpaiza Bランクレベルアップメニュー から足すか掛けるかという問題を解説します。
この問題集は繰り返しと条件分岐に関する4個のSTEP問題(D級)とFINAL問題(C級)で構成されていて、STEP問題を解いて行けばFINAL問題も解けるはず!となっています。
STEP問題を解いてみる
STEP問題は繰り返しと条件分岐の基本問題です。
簡単な解説は付けていますが、難しいと感じたら下記の記事も参考にしてみて下さい。
※過去に出題された小問題が出てくることがありますが、チケットに余裕があれば復習のつもりで取り組んでみましょう。
STEP1: インクリメント (paizaランク D 相当)
STEP1 は受け取った整数をインクリメント(+1)して出力する問題です。
解答例
<< EOS 入力例1 -10 出力例1 -9 入力例2 0 出力例2 1 入力例3 1 出力例3 2 EOS n = gets.to_i puts n + 1
解答例: 標準入力で受けとった文字列を整数型に変換、+1 して出力しています。
STEP2: 文字列の出力 (paizaランク D 相当)
STEP2 はn個
の改行区切りの文字列をそのまま出力する問題です。
解答例
<<"EOS" 入力例1 3 AB CD EF 出力例1 AB CD EF 入力例2 3 1 2 3 出力例2 1 2 3 入力例3 3 a b c 出力例3 a b c EOS # [解答例1] n = gets.to_i n.times { puts gets } # [解答例2] n = gets.to_i ary = n.times.map { gets.chomp } puts ary
解答例1: 1行目で受け取ったn回
の繰り返しを設定し、続くn行分
の文字列をそのまま出力しています。
解答例2: n行
の文字列を一旦配列ary
に格納してから、各要素を改行区切りで出力しています。
STEP3: 文字列の分割 (paizaランク D 相当)
STEP3 はスペース区切りの2つの文字列を改行区切りの2行で出力する問題です。
解答例
<<"EOS" 入力例1 Hello World 出力例1 Hello World 入力例2 apple orange 出力例2 apple orange 入力例3 12 345 出力例3 12 345 EOS # [解答例1] a, b = gets.split puts a puts b # [解答例2] ary = gets.split puts ary
解答例1: 半角スペース区切りの文字列を別の変数に代入して、それぞれ出力しています。
解答例2: 半角スペース区切りの文字列を一旦配列ary
に格納して、配列の要素を改行区切りで出力しています。
STEP4: 整数の足し算 (paizaランク D 相当)
STEP4 はスペース区切りの2つの整数を足した値を出力する問題です。
解答例
<<"EOS" 入力例1 0 0 出力例1 0 入力例2 1 2 出力例2 3 入力例3 10 20 出力例3 30 EOS # [解答例1] a, b = gets.split.map(&:to_i) puts a + b # [解答例2] puts gets.split.map(&:to_i).sum
解答例1: 半角スペース区切りの文字列を整数型に変換して別の変数に代入して、足したものを出力しています。
解答例2: 角スペース区切りの文字列を整数型に変換して配列にして、sumメソッド
で合計値を求めて出力しています。
足すか掛けるか (paizaランク C 相当)を解いてみる
※ paiza Bランクレベルアップメニューより
問題
2つの整数の組がn個与えられるので、各組の計算結果を足し合わせたものを出力してください。
各組の計算結果は次の値です。
- 2つの整数の組を足し合わせたもの
- ただし、2つの整数が同じ値だった場合は、掛け合わせたもの
入力される値
入力は以下のフォーマットで与えられます。
n
a_1 b_1
...
a_n b_n
nは与えられる整数の組の行数です。
a_iとb_iはそれぞれが整数です。
入力値最終行の末尾に改行が1つ入ります。
期待する出力
各行の計算結果を足し合わせた値を出力してください。
最後は改行し、余計な文字、空行を含んではいけません。
条件
すべてのテストケースにおいて、以下の条件をみたします。
- 1 ≦ n ≦ 50
- -100,000 ≦ a_n ≦ 100,000
- -100,000 ≦ b_n ≦ 100,000
- 入力例1
- 5
2 1
3 6
4 2
4 4
4 70
- 出力例1
- 108
- 入力例2
- 1
0 0
- 出力例2
- 0
- 入力例3
- 3
1 2
3 4
5 6
- 出力例3
- 21
攻略ポイント
ポイント
- 半角スペース区切りの整数を受け取る(二次元配列)
- 繰り返しと条件分岐の組み合わせ
デバッグを楽にするためにメソッドを作成します。メソッドについては下記の記事も参考にしてみて下さい。
問題を解く流れ
入出力例をコピペしてヒアドキュメントで変数に代入し、データを確認します。正しく受け取れていれば確認用コードは削除します。
INPUT1 = <<~"EOS" 5 2 1 3 6 4 2 4 4 4 70 EOS OUTPUT1 = <<~"EOS" 108 EOS INPUT2 = <<~"EOS" 1 0 0 EOS OUTPUT2 = <<~"EOS" 0 EOS INPUT3 = <<~"EOS" 3 1 2 3 4 5 6 EOS OUTPUT3 = <<~"EOS" 21 EOS # 確認用コード p INPUT1 # > "5\n2 1\n3 6\n4 2\n4 4\n4 70\n" p OUTPUT1 # > "108\n" p INPUT2 # > 1\n0 0\n" p OUTPUT2 # > "0\n" p INPUT3 # > "3\n1 2\n3 4\n5 6\n" p OUTPUT3 # > "21\n"
続いて問題を解くメソッド( solve
メソッドとします)を変数の下に定義します。
まず、入力データを受け取る処理を書きます。
def solve(input_lines) # 入力データ受け取り input_lines = input_lines.split("\n") n = input_lines.shift.to_i ary = [] input_lines.shift(n).each do |line| ary.push(line.split.map(&:to_i)) end # 確認用コード [n, ary] end # 確認用コード p solve(INPUT1) # > [5, [[2, 1], [3, 6], [4, 2], [4, 4], [4, 70]]] p solve(INPUT2) # > [1, [[0, 0]]] p solve(INPUT3) # > [3, [[1, 2], [3, 4], [5, 6]]]
データが正しく受け取れていれば、solve
メソッドに二次元配列ary
について計算する処理を追加していきます。
配列ary
の各要素の1番目と2番目の要素について調べる- 1番目と2番目の要素の値が同じなら掛け算をする
- 1番目と2番目の要素の値が異なるなら足し算をする
- 各要素で計算した結果を全て足して出力する
def solve(input_lines) # 入力データ受け取り input_lines = input_lines.split("\n") n = input_lines.shift.to_i ary = [] input_lines.shift(n).each do |line| ary.push(line.split.map(&:to_i)) end # 配列 ary の各要素を計算して合計を求める result = 0 ary.each do |a, b| if a == b result += a * b else result += a + b end end # 確認用コード result end p solve(INPUT1) # > 108 p solve(INPUT1) == OUTPUT1 # > false p solve(INPUT2) # > 0 p solve(INPUT2) == OUTPUT2 # > false p solve(INPUT3) # > 21 p solve(INPUT3) == OUTPUT3 # > false
あとは出力形式を整えれば完成です。
p solve(INPUT1)
を puts solve(STDIN.read)
(p solve(STDIN.read)
でも可)に変更すれば正解となりますが、p solve(INPUT1) == OUTPUT1 -> true
を確認するために、結果を改行区切りの文字列に変換して、末尾にも改行を加えます。
def solve(input_lines) # 入力データ受け取り input_lines = input_lines.split("\n") n = input_lines.shift.to_i ary = [] input_lines.shift(n).each do |line| ary.push(line.split.map(&:to_i)) end # 配列 ary の各要素を計算して合計を求める result = 0 ary.each do |a, b| if a == b result += a * b else result += a + b end end # 文字列型に変換して末尾に改行を追加する result.to_s << "\n" end p solve(INPUT1) # > "108\n" p solve(INPUT1) == OUTPUT1 # > true p solve(INPUT2) # > "0\n" p solve(INPUT2) == OUTPUT2 # > true p solve(INPUT3) # > "21\n" p solve(INPUT3) == OUTPUT3 # > true
確認用コードを標準入力からのデータ受け取りに変更して、動作確認をしたら提出します。
複数行のデータ受け取りなので STDIN.read
を使います。(入力終了は Ctrl+D
又は Ctrl+Z
)
解答コード
def solve(input_lines) # 入力データ受け取り input_lines = input_lines.split("\n") n = input_lines.shift.to_i ary = [] input_lines.shift(n).each do |line| ary.push(line.split.map(&:to_i)) end # 配列 ary の各要素を計算して合計を求める result = 0 ary.each do |a, b| if a == b result += a * b else result += a + b end end # 文字列型に変換して末尾に改行を追加する result.to_s << "\n" end puts solve(STDIN.read)
他の解答例
- 入力データの受け取りを多重代入で一括処理
- 整数ペアの計算結果の配列を生成し、sumメソッドで合計を求めて出力
def solve(input_lines) _, *lines = input_lines.split("\n") result = lines.map { |line| a, b = line.split.map(&:to_i) a == b ? a * b : a + b }.sum result.to_s << "\n" end puts solve(STDIN.read)
今回のまとめ
繰り返し処理の中でsplitメソッド
を使って二次元配列データを受け取り、条件分岐で異なる計算を行いました。
B級問題では二次元配列が多く出題されるのでmapメソッドに慣れておくと良いですね!