paiza プログラミング

[Ruby|Python]paiza paizaの森練習問題コンテスト過去問題1

forest_contest_001

paizaの森練習問題コンテストは、「paizaの森 (Discord)」にて約2か月に1回のペースで開催されており、ユーザー同士が開催時刻にpaizaの森に集まり「よーいドン」で与えられた数問(第1回は4問)の練習問題をお好きなプログラミング言語で解答する早さを競います。
それほど難しい問題は出題されないですし、誤答によるペナルティーもありませんので初心者でも気軽に参加出来ます。
また、コンテストから数日後には出題された問題が一般公開され、だれでも挑戦できるようになります。

本記事で使用しているメソッド・アルゴリズムについて

解答例で使っているメソッドやアルゴリズムについて、下記の記事で詳しく解説していますので参考にしてみて下さい。

第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の中の人が実況してくれるので、実況を聞いてみるのも楽しいと思いますよ(*'ω'*)



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


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






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







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







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







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


-paiza, プログラミング

© 2024 じゃいごテック