paizaの森練習問題コンテストは、「paizaの森 (Discord)」にて約2か月に1回のペースで開催されており、ユーザー同士が開催時刻にpaizaの森に集まり「よーいドン」で与えられた数問(第1回は4問)の練習問題をお好きなプログラミング言語で解答する早さを競います。
それほど難しい問題は出題されないですし、誤答によるペナルティーもありませんので初心者でも気軽に参加出来ます。
また、コンテストから数日後には出題された問題が一般公開され、だれでも挑戦できるようになります。
本記事で使用しているメソッド・アルゴリズムについて
解答例で使っているメソッドやアルゴリズムについて、下記の記事で詳しく解説していますので参考にしてみて下さい。
- [Ruby] 標準入力によるデータ取得1
- [Ruby] 標準入力によるデータ取得2
- [Ruby] 標準入力によるデータ取得3
- [Ruby] 標準出力(データを任意に整形して出力する)
- [Ruby]配列の基本操作1
- [Ruby]繰り返し処理
- [Ruby]条件分岐
- [Ruby]ハッシュ(連想配列)
第1回 paizaの森練習問題コンテスト
1問目: スポーツの人数 (paizaランク D 相当)
球技の名前と競技人数が問題文で与えられ、標準入力から英語の球技名 s
が与えられたときに、競技人数を出力する問題です。
【球技名と競技人数】
- 野球 baseball : 9 人
- サッカー soccer : 11 人
- ラグビー rugby : 15 人
- バスケットボール basketball : 5 人
- バレーボール volleyball : 6 人
入出力例
球技名s
が与えられ、競技人数(チームの人数)を出力します。(例: 野球 baseball -> 9人 なので 9 を出力する。)
INPUT1 = <<~"EOS" baseball EOS OUTPUT1 = <<~"EOS" 9 EOS
Ruby 解答例1
if文を使って、与えられた球技の数だけ条件分岐を書きます。
# 入力 s = gets.chomp # 球技の人数を出力 if s == "baseball" puts 9 elsif s == "soccer" puts 11 elsif s == "rugby" puts 15 elsif s == "basketball" puts 5 elsif s == "volleyball" puts 6 end
Ruby 解答例2
case文を使って、与えられた球技の数だけ条件分岐を書きます。
# 入力 s = gets.chomp # 球技の人数を出力 case s when "baseball" puts 9 when "soccer" puts 11 when "rugby" puts 15 when "basketball" puts 5 when "volleyball" puts 6 end
Ruby 解答例3
ハッシュ(連想配列)のキーに球技名、値に競技人数を格納しておくと、条件分岐を書く必要がなくなります。
ハッシュ部分は問題文からコピーして、球技名を""で囲み、「:」を「=>」に置換すればOK!
# 問題文からコピーしてきて・・・ baseball : 9 soccer : 11 rugby : 15 basketball : 5 volleyball : 6 # 編集する # ↓↓↓ sports = { "baseball" => 9, "soccer" => 11, "rugby" => 15, "basketball" => 5, "volleyball" => 6 }
# 球技の人数 sports = { "baseball" => 9, "soccer" => 11, "rugby" => 15, "basketball" => 5, "volleyball" => 6 } # 入力 s = gets.chomp # 球技の人数を出力 puts sports[s]
Python3 解答例1
if文を使って、与えられた球技の数だけ条件分岐を書きます。
(Python3 に case文・switch文 はありません。)
# 入力 s = input() # 球技の人数を出力 if s == "baseball": print(9) elif s == "soccer": print(11) elif s == "rugby": print(15) elif s == "basketball": print(5) elif s == "volleyball": print(6)
Python3 解答例2
辞書(連想配列)のキーに球技名、値に競技人数を格納しておくと、条件分岐を書く必要がなくなります。
# 球技の人数 sports = { "baseball": 9, "soccer": 11, "rugby": 15, "basketball": 5, "volleyball": 6 } # 入力 s = input() # 球技の人数を出力 print(sports[s])
2問目: バイトの休憩時間 (paizaランク D 相当)
勤務時間が整数 h (4 ≤ h ≤ 12)
で与えられ、休み時間を既定のフォーマットで出力する問題です。
【休み時間の規定】
- 勤務時間が6時間以下のときには、0分 →
no break
と出力する - 勤務時間が6時間を超え、8時間以下であるときには、45分 →
45 min
と出力する - 勤務時間が8時間を超えるときには、60分 →
60 min
と出力する
入出力例
INPUT1 = <<~"EOS" 9 EOS OUTPUT1 = <<~"EOS" 60 min EOS INPUT2 = <<~"EOS" 6 EOS OUTPUT2 = <<~"EOS" no break EOS
Ruby解答例1
3種類の条件分岐で実装します。これが一番早いかな?と思います。
# 入力 h = gets.to_i # 休憩時間を出力 if h > 8 puts "60 min" elsif h > 6 puts "45 min" else puts "no break" end
Ruby解答例2
休憩時間を整数型変数に格納する方式です。
# 入力 h = gets.to_i # 休憩時間 break_time = 0 if h > 8 break_time += 60 elsif h > 6 break_time += 45 end # 休憩時間を出力 if break_time == 0 puts "no break" else puts "#{break_time} min" end
Python解答例1
3種類の条件分岐で実装する方法です。
# 入力 h = int(input()) # 休憩時間を出力 if h > 8: print("60 min") elif h > 6: print("45 min") else: print("no break")
Python解答例2
休憩時間を整数型変数に格納する方式です。
# 入力 h = int(input()) # 休憩時間を計算 break_time = 0 if h > 8: break_time += 60 elif h > 6: break_time += 45 # 休憩時間を出力 if break_time == 0: print("no break") else: print(f"{break_time} min")
3問目: 自動車の燃費 (paizaランク D 相当)
整数の給油量 v
(20 ≤ v ≤ 100) と整数の走行距離 d
(300 ≤ d ≤ 1500) が与えられ、燃費の小数点以下を切り捨てて出力する問題です。
入出力例
INPUT1 = <<~"EOS" 65 600 EOS OUTPUT1 = <<~"EOS" 9 EOS INPUT2 = <<~"EOS" 36 831 EOS OUTPUT2 = <<~"EOS" 23 EOS
Ruby解答例1
燃費 = 走行距離 d / 給油量 v の計算をすれば良いだけなので、あまり工夫の余地はないですね。
(Rubyでは、整数と整数を演算子「/」で除算すると、小数点を切り捨てた整数部分が返ってきます。)
# 入力 v, d = gets.split.map(&:to_i) # 燃費を出力 puts d / v
Ruby解答例2
divメソッドというものもあります。
# 入力 v, d = gets.split.map(&:to_i) # 燃費を出力 puts d.div(v)
Python3 解答例1
Python3では、整数と整数を演算子 「/」で除算すると、float型が返ってきますので、演算子「//」で計算します。
# 入力 v, d = map(int, input().split()) # 燃費を出力 print(d // v)
Python3 解答例2
divmod関数を使うと、商と剰余を同時に求められます。
# 入力 v, d = map(int, input().split()) # 燃費を出力 print(divmod(d, v)[0])
4問目: 背番号順 (paizaランク C 相当)
1行目で選手の人数 n が与えられ、続く n 行の半角スペース区切りで背番号 b と、選手名 p が与えられますので、
n 人の選手を背番号の数値が小さい方から順に並び替えて、「背番号 + 半角スペース + 選手名」 の形式で、一人ずつ改行して出力する問題です。
【ポイント】 背番号の数値が小さい方から並び替える必要がある。
- [2, 12, 1].sort → [1, 2, 12] ・・・OK
- ["2", "12", "1"].sort → ["1", "12", "2"] ・・・NG
入出力例
INPUT1 = <<~"EOS" 3 83 PAIZA 11 SUZUKI 90 TANAKA EOS OUTPUT1 = <<~"EOS" 11 SUZUKI 83 PAIZA 90 TANAKA EOS INPUT2 = <<~"EOS" 5 31 SAITO 56 GORO 11 IIJIMA 70 NAKAMURA 1 HAJIME EOS OUTPUT2 = <<~"EOS" 1 HAJIME 11 IIJIMA 31 SAITO 56 GORO 70 NAKAMURA EOS
Ruby解答例1
- 整数 n を受け取る
- 選手リスト(Array) players を空で初期化する
- n 回のループを回す
- 1行分のデータを半角スペースで分割、背番号 number, 選手名 name に格納
- 背番号 number を整数に変換し、
[number(int), name(str)]
を 選手リスト players に追加
ここまでで、入力例1だとこんな感じになる
players = [[83, "PAIZA"], [11, "SUZUKI"], [90, "TANAKA"]]
- 選手リスト players を1番目の要素(背番号 number)で昇順ソート
- 選手リスト players を先頭から順に参照するループを設定
- 「背番号 number + 半角スペース + 選手名 name」(+改行)を出力
Ruby 解答例1
# 入力 n = gets.to_i players = [] n.times do number, name = gets.split players << [number.to_i, name] end # 選手リストを背番号で昇順ソート players.sort! # これでも同じ # players.sort_by! { |x| x[0] } # 出力 players.each do |number, name| puts "#{number} #{name}" end
Ruby 解答例2
必要な情報だけを一括で受け取り、選手情報が「背番号 + 半角スペース + 選手名」の形式になっているので、to_iメソッドで背番号を整数化できることを利用した方法です。
通常だと良くない実装かもしれませんが、問題を解く早さを競うコンテストなので!
# 入力 _, *players = STDIN.read.split("\n") # ソートして出力 puts players.sort_by { |x| x.to_i }
Python3 解答例1
# 入力 n = int(input()) players = [] for _ in range(n): number, name = input().split() players.append([int(number), name]) # 背番号で昇順ソート players.sort() # これでも同じ # players.sort(key=lambda x: x[0]) # 出力 for (number, name) in players: print(f"{number} {name}")
Python3 解答例2
Python3だと、「背番号 + 半角スペース + 選手名」を直接整数型に変換しようとするとエラーが出てしまうので、結局split()しています。
# 入力 _, *players = open(0).read().strip().split("\n") # 背番号で昇順ソート players.sort(key=lambda x: int(x.split()[0])) # 出力 print(*players, sep="\n")
今回のまとめ
paizaのD~Cランク問題が解けるようになってきたら、paizaの森練習問題コンテストに参加して他のユーザーと競いながらレベルアップを狙ってみてはいかがでしょうか?また、paizaの森に参加している方なら見学もできますので、とりあえずどんな感じか見学してみるのも良いかもしれません。
コンテスト中はpaizaの中の人が実況してくれるので、実況を聞いてみるのも楽しいと思いますよ(*'ω'*)