paiza プログラミング

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

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

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

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

第2回 paizaの森練習問題コンテスト

1問目: 競輪のユニフォーム (paizaランク D 相当)

1~9のそれぞれに色が割り当てられていて、標準入力から番号 n が与えられたときに、その番号に対応した色を出力する問題です。

【番号と色の対応】

  • 1: white
  • 2: black
  • 3: red
  • 4: blue
  • 5: yellow
  • 6: green
  • 7: orange
  • 8: pink
  • 9: purple
入出力例

番号n が与えられ、色を出力します。(例:2 が入力されたら、 black を出力する。)

INPUT1 = <<"EOS"
2
EOS
OUTPUT1 = <<"EOS"
black
EOS

INPUT2 = <<"EOS"
5
EOS
OUTPUT2 = <<"EOS"
yellow
EOS
Ruby 解答例1

if文を使って、1から9までの条件分岐を書きます。

# 解答例1
# 入力
n = gets.to_i

# n に対応した色を color に代入
color = if n == 1
  "white"
elsif n == 2
  "black"
elsif n == 3
  "red"
elsif n == 4
  "blue"
elsif n == 5
  "yellow"
elsif n == 6
  "green"
elsif n == 7
  "orange"
elsif n == 8
  "pink"
elsif n == 9
  "purple"
end

# color を出力
puts color
Ruby 解答例2

case文でも書くことが出来ます。

# 解答例2
# 入力
n = gets.to_i

# n に対応した色を color に代入
color = case n
  when 1
    "white"
  when 2
    "black"
  when 3
    "red"
  when 4
    "blue"
  when 5
    "yellow"
  when 6
    "green"
  when 7
    "orange"
  when 8
    "pink"
  when 9
    "purple"
  end

# color を出力
puts color
Ruby 解答例3

番号順の色の配列を用意しておけば、条件分岐を書かずに番号対応した色が取得できます。

# 解答例3
# 色の設定
colors = ["white", "black", "red", "blue", "yellow", "green", "orange", "pink", "purple"]

# なるべく少ない入力で配列を作るなら
# split メソッド
# colors = "white black red blue yellow green orange pink purple".split
# % 記法
# colors = %w(white black red blue yellow green orange pink purple)

# 入力
n = gets.to_i

# n に対応した色を出力
puts colors[n - 1]
Python3 解答例1

if文を使って、1から9までの条件分岐を書きます。

# 解答例1
# 入力
n = int(input())

# n に対応した色を color に代入
color = ""
if n == 1:
    color = "white"
elif n == 2:
    color = "black"
elif n == 3:
    color = "red"
elif n == 4:
    color = "blue"
elif n == 5:
    color = "yellow"
elif n == 6:
    color = "green"
elif n == 7:
    color = "orange"
elif n == 8:
    color = "pink"
elif n == 9:
    color = "purple"

# color を出力
print(color)
Python3 解答例2

番号順の色の配列を用意しておけば、条件分岐を書かずに番号対応した色が取得できます。

# 解答例2
# 色の設定
colors = ["white", "black", "red", "blue", "yellow", "green", "orange", "pink", "purple"]

# なるべく少ない入力で配列を作るなら
# colors = "white black red blue yellow green orange pink purple".split()

# 入力
n = int(input())

# n に対応した色を出力
print(colors[n - 1])

 


2問目: エレベーターの行き先 (paizaランク D 相当)

エレベータに乗った想定で、現在いる階 f1 と行きたい階 f2 が半角スペース区切りで与えられるので、"up" と "down" のどちらのボタンを押せば良いかを出力する問題です。
尚、f1, f21F, 2F, 3F, 4F, 5F, 6F, 7F, 8F, 9F で与えられ、f1f2 が同じになることはありません。

入出力例

現在 1F で、 7F に行きたいなら up を出力。
現在 5F で、 2F に行きたいなら down を出力。

INPUT1 = <<"EOS"
1F 7F
EOS
OUTPUT1 = <<"EOS"
up
EOS

INPUT2 = <<"EOS"
5F 2F
EOS
OUTPUT2 = <<"EOS"
down
EOS
Ruby解答例1

"数字+F" の数字部分を整数型に変換してf1, f2に代入し、押すボタンを判別する方法です。

# 解答例1
# 入力

# input_strings = gets.split  # 文字列を半角スペースで分割して配列を生成
# f1 = input_strings[0].to_i  # 1 番目の文字列を整数に変換
# f2 = input_strings[1].to_i  # 2 番目の文字列を整数に変換

# 上記を短くまとめて書くと
f1, f2 = gets.split.map(&:to_i)

# f1 と f2 を比較して押すボタンを出力
if f1 < f2
  puts "up"
else
  puts "down"
end
Ruby解答例2

今回の問題では 1F ~ 9F までなので、文字列のまま比較することが出来ます。ついでに三項演算子で入力数削減。

# 解答例2
# 入力
f1, f2 = gets.split

# f1 と f2 を文字列のまま比較して押すボタンを出力
puts f1 < f2 ? "up" : "down"
Python解答例1

"数字+F" の数字部分を整数型に変換してf1, f2に代入し、押すボタンを判別する方法です。

# 解答例1
# 入力
# input_strings = input().split()  # 文字列を半角スペースで分割して配列を生成
# f1 = int(input_strings[0][:-1])  # 1 番目の文字列の末尾 (F) を削除して整数に変換
# f2 = int(input_strings[1][:-1])  # 2 番目の文字列の末尾 (F) を削除して整数に変換

# 上記を短くまとめて書くと
f1, f2 = map(lambda x: int(x[:-1]), input().split())

# f1 と f2 を比較して押すボタンを出力
if f1 < f2:
    print("up")
else:
    print("down")
Python解答例2

文字列のまま比較し、三項演算子で入力数削減。

# 解答例2
# 入力
f1, f2 = input().split()

# f1 と f2 を文字列のまま比較して押すボタンを出力
print("up" if f1 < f2 else "down")

 


3問目: 長方形の面積 (paizaランク D 相当)

長方形の隣接する2辺 e1,e2 が半角スペース区切り与えられ、面積を出力する問題です。
ただし、e1e2 が 0 の場合は、 invalid を出力します。

入出力例

e1 = 7, e2 = 5 なら 7 * 5 = 3535 を出力する。
e1 = 0, e2 = 10 なら invalid を出力する。

INPUT1 = <<"EOS"
7 5
EOS
OUTPUT1 = <<"EOS"
35
EOS

INPUT2 = <<"EOS"
0 10
EOS
OUTPUT2 = <<"EOS"
invalid
EOS

 

Ruby解答例1

e1, e2 のどちらかが0 だと面積も0になるので、とりあえず先に面積 s = e1 * e2 の計算を行い、s が 0 を超えるなら s を出力、 s が 0 なら invalid を出力します。

# 解答例1
# 入力
# input_strings = gets.split  # 半角スペースで分割して文字列の配列を生成
# e1 = input_strings[0].to_i  # 1 番目の文字列を整数に変換
# e2 = input_strings[1].to_i  # 2 番目の文字列を整数に変換

# ↓ 短く書くと

e1, e2 = gets.split.map(&:to_i)

# 面積計算
s = e1 * e2

# 面積 s または invalid を出力
if s > 0
  puts s
else
  puts "invalid"
end
Ruby解答例2

e1, e2 を配列で受け取り、inject メソッドで配列の総積s(e1 * e2)を求め、s が 0 を超えるなら s を出力、 s が 0 なら invalid を出力します。

# 解答例2
# 入力から面積を計算
# 半角スペースで区切られた文字列を整数の配列にして、
# 配列の要素を全て掛け合わせた値(総積)を s に格納する
s = gets.split.map(&:to_i).inject(:*)

# 面積 s または invalid を出力
puts s > 0 ? s : "invalid"
Python3 解答例1

面積 s = e1 * e2 の計算を行い、s が 0 を超えるなら s を出力、 s が 0 なら invalid を出力します。

# 解答例1
# 入力
# input_strings = input().split()  # 半角スペースで分割して文字列の配列を生成
# e1 = int(input_strings[0])       # 1 番目の文字列を整数に変換
# e2 = int(input_strings[1])       # 2 番目の文字列を整数に変換

# ↓ 短く書くと

e1, e2 = map(int, input().split())

# 面積計算
s = e1 * e2

# 面積 s または invalid を出力
if s > 0:
    print(s)
else:
    print("invalid")
Python3 解答例2

e1, e2 を配列で受け取り、math.prod メソッドで配列の総積s(e1 * e2)を求め、s が 0 を超えるなら s を出力、 s が 0 なら invalid を出力します。

# 解答例2
import math

# 入力から面積を計算
# 半角スペースで区切られた文字列を整数の配列にして、
# 配列の要素を全て掛け合わせた値(総積)を s に格納する
s = math.prod(map(int, input().split()))

# 面積 s または invalid を出力
print(s if s > 0 else "invalid")

 

4問目: セール販売 (paizaランク C 相当)

1行目で購入商品数 n が与えられ、続く n 行の半角スペース区切りで購入品名と価格が与えられ、合計金額を求める問題です。
但し、合計金額には以下のルールが適用されます。

  • ズボン(pants)を1点以上買っていて、
  • 2000円以上お買い上げ

の方は、合計金額から 500円 引きとなります。

入出力例

"shirt 1000", "shoes 2000", "shirt 500" を購入した場合、合計金額は 3500円なので 3500 を出力
"shirt 500", "pants 1000", "pants 500", "shoes 2000" を購入した場合の合計金額は 4000円となるが、pants を1点以上購入かつ合計金額が2000円以上なので 4000-500 = 3500円 で 3500 を出力

INPUT1 = <<"EOS"
3
shirt 1000
shoes 2000
shirt 500
EOS
OUTPUT1 = <<"EOS"
3500
EOS
INPUT2 = <<"EOS"
4
shirt 500
pants 1000
pants 500
shoes 2000
EOS
OUTPTU2 = <<"EOS"
3500
EOS

 

Ruby解答例1
  • 整数 n を受け取る
  • lines(Array) を空で初期化する
  • n 回のループを回す
    • 1行分の文字列を lines 末尾に追加
  • items (Array) を空で初期化する
  • total を 0 で初期化する
  • lines の先頭から順に line で参照するループを設定
    • line を半角スペースで分割して, item, price へ代入する
    • itemitems 末尾に追加する
    • price を整数型に変換して、total に加算する
  • もし「ズボン(pants) を1点以上購入」かつ「total が 2000 以上」なら total から 500 減算する
  • total を出力する
Ruby 解答例1
# 解答例1
# 入力
n = gets.to_i                    # 1 行の入力を受け取って整数型に変換
lines = []                       # 購入履歴を格納するための空のリストを用意
n.times { lines << gets.chomp }  # n 行の入力を受け取って lines に追加

# 上記を短く書くと(n は不要になる)
# _, *lines = $stdin.read.split("\n")

# 購入品 item と合計金額 total を記録する
items = []
total = 0
lines.each do |line|
  item, price = line.split
  items << item
  total += price.to_i
end

# もし "pants" を購入かつ total が 2000 円以上なら 500 円引き
if items.include?("pants") && total >= 2000
  total -= 500
end

puts total
Ruby 解答例2

購入品のリストを作る代わりに、pants を買ったかどうかのフラグを設定する書き方です。

# 解答例2
# 入力
_, *lines = $stdin.read.split("\n")

# "pants" を買ったか?のフラグ と合計金額 total を記録する
pants = false
total = 0
lines.each do |line|
  item, price = line.split
  pants = true if item == "pants"
  total += price.to_i
end

# もし pants を購入かつ total が 2000 円以上なら 500 円引き
if pants && total >= 2000
  total -= 500
end

puts total
Python3 解答例1
# 解答例1
# 入力
# n = int(input())            # 1 行の入力を受け取って整数型に変換
# lines = []                  # 空のリストを用意
# for _ in range(n):
#     lines.append(input())   # n 行の入力を受け取って配列 list 末尾に追加

# 上記を短く書くと (n は不要になる)
_, *lines = open(0).read().strip().split("\n")

# 品物 item のリストと合計金額 total を記録する
items = []
total = 0
for line in lines:
    item, price = line.split()
    items.append(item)
    total += int(price)

# もし "pants" を購入かつ total が 2000 円以上なら 500 円引き
if "pants" in items and total >= 2000:
    total -= 500

print(total)
Python3 解答例2
# 解答例2
# 入力
_, *lines = open(0).read().strip().split("\n")

# 合計金額 total と "pants" を買ったかを記録する
pants = False
total = 0
for line in lines:
    item, price = line.split()
    if item == "pants":
        pants = True 
    total += int(price)

# もし pants を購入かつ total が 2000 円以上なら 500 円引き
if pants and total >= 2000:
    total -= 500

print(total)

 


今回のまとめ

基本的な文法(標準入力・出力、配列、繰り返し、条件分岐)が出来れば特に難しくない問題でした。

手数(打鍵数)が少ない書き方も覚えておけば、タイムアタックの時に便利かもしれませんね(*'ω'*)



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


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






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







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







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







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


-paiza, プログラミング

© 2023 じゃいごテック