この記事では
プログラミング学習サービスpaizaラーニングの
スキルチェックレベルアップ問題集をわかりやすく解説します!
またプログラミング言語はpythonです。
今回はAランク相当の以下の問題を解説します。
他のレベルアップ問題集の解答と解説も紹介しているので
ぜひご参考ください!
またpaizaの各ランクの攻略法は
こちらで詳しく紹介しているので、ぜひご参考ください!
この問題を解くための3つのポイント
まずは「この問題を解くためのポイント」をご説明します。
問題はこちらからご確認ください。
この問題を解くためのポイントは3つです。
- 合計の指の本数を満たす組み合わせを探す
- 無駄な処理を減らす
- 勝利数を求める
合計の指の本数を満たす組み合わせを探す
まずは「合計の指の本数を満たす組み合わせを探す」です。
今回の問題では、じゃんけんで出す指の合計の数が
入力によって指定されます。
グーの場合は指の本数が0なので、
チョキとパーの組み合わせを全て探さなればいけません。
そのためチョキとパーの回数に関して、
for文を使って組み合わせを探します。
''' numがじゃんけんの回数 '''
# チョキの回数(範囲:0 ~ num)
for i in range(0, num + 1):
# パーの回数(範囲:0 ~ num)
for j in range(0, num + 1):
range関数で範囲を指定する時は、
範囲を間違えないように注意しましょう!
for文については、こちらをご参考ください!
次に合計の本数を満たすかの条件をif文で課します。
'''
numがじゃんけんの回数
fingerが合計の指の数
'''
# パーの回数(範囲:0 ~ num)
for i in range(num + 1):
# チョキの回数(範囲:0 ~ num)
for j in range(num + 1):
# 合計の数がfingerと等しい時
if 5*i + 2*j == finger:
if文については、こちらをご参考ください!
無駄な処理を減らす
次は「無駄な処理を減らす」です。
上記の「合計の指の本数を満たす組み合わせを探す」で紹介したfor文には
無駄な範囲が含まれており
処理速度が遅くなってしまうので範囲を限定します。
限定する方法は以下の2つです。
- チョキとパーを出す回数の合計
- チョキとパーを出せる最大の回数
まずは「チョキとパーを出す回数の合計」です。
今回の問題ではじゃんけんの回数が入力で指定されるため
チョキとパーを出す回数の合計は必ずじゃんけんの回数よりも少なくなります。
そのためチョキの回数のfor文の範囲を狭められます。
# パーの回数(範囲:0 ~ num)
for i in range(num + 1):
# iが大きいほどチョキの範囲が狭まる
for j in range(num + 1 - i):
次は「チョキやパーを出せる最大の回数」です。
今回の問題ではじゃんけんで出す指の合計本数が指定されるため
チョキとパーを出せる回数には、上限があります。
- チョキ:
(合計の指の本数)÷
2 - パー :
(合計の指の本数)÷5
そのためfor文の範囲を狭めることが出来ます。
# パーを出せる最大の回数
max_p = finger // 5
# パーの回数(範囲:0 ~ num)
for i in range(max_p + 1):
# iが大きいほどチョキの範囲が狭まる
for j in range(num + 1 - i):
ここでチョキの回数の範囲を変更していないのは
num + 1 - i
の方が上限より小さくなる場合があり
それを判定するほうが処理に時間がかかるためです。
割り算などの四則演算については、こちらをご参考ください!
勝利数を求める
最後は「勝利数を求める」です。
今回の問題では相手が出すそれぞれの手の回数がわかっているので
自分の出す手の回数と比較して、小さい方を勝利数として計算します。
そのためmin関数を使って、それぞれの手での勝利数を計算して合計します。
'''
g, p, c が相手のグー、パー、チョキの回数
i, j が自分のパー、チョキの回数
'''
# 自分がパーを出して勝つ回数
win = min(g, i)
# 自分がチョキを出して勝つ回数
win += min(p, j)
# 自分がグーを出して勝つ回数
win += min(c, num - i - j)
また1行で書くと、よりシンプルです。
# 勝利数を計算
win = min(g, i) + min(p, j) + min(c, num - i - j)
じゃんけんの手の出し方 (paizaランク A 相当)の解答
ではここまで紹介したポイントを使って、問題を解いていきます。
入力を受け取り、相手の出す手の回数を変数に代入
まずは「入力を受け取り、相手の出す手の回数を変数に代入」です。
今回の問題では1行目でじゃんけんの回数と指の合計の本数が
半角スペース区切りで入力されます。
そのためsplit関数を使って2つの変数に代入し、int型に変換します。
# じゃんけんの回数と指の合計の本数の入力を受け取る
num, finger = input().split()
# int型に変換
num = int(num)
finger = int(finger)
int型などの変数の型については、こちらをご参考ください!
また内包表記を使うと1行で書けるため、よりシンプルです。
# じゃんけんの回数と指の合計の本数の入力を受け取り、int型に変換
num, finger = [int(x) for x in input().split()]
内包表記については、こちらをご参考ください!
2行目では、相手の出す手が入力されるので変数に代入します。
# 相手の出す手の入力を受け取る
hands = input()
次にcountメソッドを使ってそれぞれの手の回数を求めます。
# 相手の出す手の入力を受け取る
hands = input()
# 相手がグーを出す回数
g = hands.count("G")
# 相手がチョキを出す回数
c = hands.count("C")
# 相手がパーを出す回数
p = num - g - c
入力については、こちらをご参考ください!
勝利数が最大の自分の手の組み合わせを求めて出力
次は「勝利数が最大の自分の手の組み合わせを求めて出力」です。
まず合計の指の本数を満たす組み合わせを求め
その場合の勝利数を計算します。
''' パーを出せる最大の回数 '''
max_p = finger // 5
# パーの回数(範囲:0 ~ num)
for i in range(max_p + 1):
# チョキの回数(範囲:0 ~ num - i)
for j in range(num + 1 - i):
# 合計の数がfingerと等しい時
if 5*i + 2*j == finger:
# 勝利数を計算
win = min(g, i) + min(p, j) + min(c, num - i - j)
次に勝利数を代入する変数を定義し
max関数を使って計算した勝利数が、以前より大きい場合のみ更新します。
# パーを出せる最大の回数
max_p = finger // 5
# 最大の勝利数を代入する変数を定義
max_win = 0
# パーの回数(範囲:0 ~ num)
for i in range(max_p + 1):
# チョキの回数(範囲:0 ~ num - i)
for j in range:
# 合計の数がfingerと等しい時
if 5*i + 2*j == finger:
# 勝利数を計算
win = min(g, i) + min(p, j) + min(c, num - i - j)
# 以前より大きい場合のみ更新
max_win = max(max_win, win)
最後にprint関数を使って結果を出力します。
# 最大の勝利数を出力
print(max_win)
出力については、こちらをご参考ください!
解答
全てまとめると解答は以下です。
# じゃんけんの回数と指の合計の本数の入力を受け取り、int型に変換
num, finger = [int(x) for x in input().split()]
# 相手の出す手の入力を受け取る
hands = input()
# 相手がグーを出す回数
g = hands.count("G")
# 相手がチョキを出す回数
c = hands.count("C")
# 相手がパーを出す回数
p = num - g - c
# パーを出せる最大の回数
max_p = finger // 5
# 最大の勝利数を代入する変数を定義
max_win = 0
# パーの回数(範囲:0 ~ num)
for i in range(max_p + 1):
# チョキの回数(範囲:0 ~ num - i)
for j in range(num + 1 - i):
# 合計の数がfingerと等しい時
if 5*i + 2*j == finger:
# 勝利数を計算
win = min(g, i) + min(p, j) + min(c, num - i - j)
# 以前より大きい場合のみ更新
max_win = max(max_win, win)
# 最大の勝利数を出力
print(max_win)
ぜひご参考ください!
まとめ
今回はpaizaのレベルアップ問題集の中で
- じゃんけんの手の出し方 (paizaランク A 相当)
の解答と解説を紹介しました。
Aランクの問題になると、例え正しい出力が得られたとしても
「ランタイムエラー」で減点されることが増えてくるかと思います。
アルゴリズムを考える時はもちろん提出前にも
無駄な処理がないかどうかをちゃんと確認しましょう!
また他のレベルアップ問題集の問題についての解説も、ぜひご参考ください!