この記事では
プログラミング学習サービスpaizaラーニングの
スキルチェックのレベルアップ問題集の問題について
わかりやすく解説します!
またプログラミング言語はpythonです。
今回はBランク相当の日別訪問者数の最大平均区間について解説します。
問題はこちらからご確認ください!
スキルチェック過去問題:日別訪問者数の最大平均区間 (paizaランク B 相当)
他のレベルアップ問題集の解答と解説もしているので
ぜひご参考ください!
またpaizaの各ランクの攻略法は
こちらで詳しく紹介しているので、ぜひご参考ください!
この問題を解くための3つのポイント
まずは「この問題を解くためのポイント」をご説明します。
この問題を解くためのポイントは以下の3つです。
- 各期間の訪問者数を計算する回数を考える
- 訪問者数が最大の期間を数える
- 期間の開始日も記録する
各期間の訪問者数を計算する回数を考える
まずは「各期間の訪問者数を計算する回数を考える」についてです。
今回の問題では
- 全日数
- キャンペーンの日数
- 1日ごとの訪問者数
の3つが入力され、キャンペーンの日数と1日ごと訪問者数から
- キャンペーンの候補数
- キャンペーン候補の最も早い開始日
の2つを結果として出力します。
そのため全日数をキャンペーンの日数で分け
for文を使って各期間の訪問者数を計算しなければなりません。
そこで必要になるのが処理を繰り返す回数です。
例えば「全日数が5日、キャンペーンの日数が3日」の場合は
- 1日目~3日目
- 2日目~4日目
- 3日目~5日目
の3つの期間の訪問者数を計算する必要があります。
そして処理を繰り返す日数は
(全日数) – (キャンペーンの日数) + 1
で求められます!
""" totalは全日数 periodはキャンペーンの日数 """ # "(全日数)-(キャンペーンの日数)+1"回処理を繰り返す for i in range(total - period + 1): # 各期間に対する処理を書く
for文と四則演算についてはこちらをご参考ください!
訪問者数が最大の期間を数える
次に「訪問者数が最大の期間を数える」についてです。
今回の問題では「各期間の平均訪問者数が最大の区間」を
キャンペーン期間を候補として考えます。
そのため、最初に1日ごとの訪問者数のリストをスライスして
各期間の訪問者数のリストを作成します。
# "(全日数)-(キャンペーンの日数)+1"回処理を繰り返す for i in range(total - period + 1): # 各期間に訪問者数のリスト part_visitors = visitors[i:i+period]
リストのスライスについては、こちらをご参考ください!
次に平均訪問者数が最大であれば合計訪問者数も最大なので
sum関数を使って合計訪問者数を計算します。
# "(全日数)-(キャンペーンの日数)+1"回処理を繰り返す for i in range(total - period + 1): # 各期間に訪問者数のリスト part_visitors = visitors[i:i+period] # 各期間の合計訪問者数 sum_visit = sum(part_visitors)
また新たにリストを作らず1行で書くとよりシンプルです。
# "(全日数)-(キャンペーンの日数)+1"回処理を繰り返す for i in range(total - period + 1): # 各期間の合計訪問者数 sum_visit = sum(visitors[i:i+period])
次に最大の合計訪問者数とその期間の数を記録する変数を用意します。
# 最大の合計訪問者数 max_visit = 0 # 合計訪問者数が最大の期間の数 count = 0 # "(全日数)-(キャンペーンの日数)+1"回処理を繰り返す for i in range(total - period + 1): # 各期間の合計訪問者数 sum_visit = sum(visitors[i:i+period])
次にif elif文を使って
- 各期間の合計訪問者数がこれまでの最大より大きいか
- 各期間の合計訪問者数がこれまでの最大と同じか
の2つの条件で条件分岐を行います。
# 最大の合計訪問者数 max_visit = 0 # 合計訪問者数が最大の期間の数 count = 0 # "(全日数)-(キャンペーンの日数)+1"回処理を繰り返す for i in range(total - period + 1): # 各期間の合計訪問者数 sum_visit = sum(visitors[i:i+period]) # これまでの最大合計訪問者数より大きい場合 if sum_visit > max_visit: # これまでの最大合計訪問者数と同じ場合 elif sum_visit == max_visit:
if文についてはこちらをご参考ください!
そしてそれぞれの条件を満たすとき
最大の合計訪問者数とキャンペーン期間の候補数に以下の処理を行います。
- 各期間の合計訪問者数がこれまでの最大より大きい場合
- 最大の合計訪問者数の値を更新
- キャンペーン期間の候補数を1にする
- 各期間の合計訪問者数がこれまでの最大と同じ場合
- キャンペーン期間の候補数を1増やす
# 最大の合計訪問者数 max_visit = 0 # キャンペーン期間の候補数 count = 0 # "(全日数)-(キャンペーンの日数)+1"回処理を繰り返す for i in range(total - period + 1): # 各期間の合計訪問者数 sum_visit = sum(visitors[i:i+period]) # これまでの最大合計訪問者数より大きい場合 if sum_visit > max_visit: # 最大の合計訪問者数を更新 max_visit = sum_visit # キャンペーン期間の候補数をリセット count = 1 # これまでの最大合計訪問者数と同じ場合 elif sum_visit == max_visit: # キャンペーン期間の候補数を1増やす count += 1
四則演算についてはこちらをご参考ください!
期間の開始日も記録する
最後に「期間の開始日も記録する」についてです。
今回の問題では最終的な結果として
キャンペーンの候補数だけでなく、最も早い開始日も出力しなければなりません。
そのために開始日を記録する変数を用意します。
# キャンペーン候補の開始日 date = 0
そして各期間の合計訪問者数が更新された場合に
for文のインデックスを使って開始日も更新します。
# 最大の合計訪問者数 max_visit = 0 # キャンペーン期間の候補数 count = 0 # キャンペーンの開始日 date = 0 # "(全日数)-(キャンペーンの日数)+1"回処理を繰り返す for i in range(total - period + 1): # 各期間の合計訪問者数 sum_visit = sum(visitors[i:i+period]) # これまでの最大合計訪問者数より大きい場合 if sum_visit > max_visit: # 最大の合計訪問者数を更新 max_visit = sum_visit # キャンペーン期間の候補数をリセット count = 1 # キャンペーンの開始日を更新 date = i + 1
ただしfor文のインデックスは0から始まりキャンペーンの開始日と1ずれるため
インデックスに1を加えることに注意しましょう!
for文については、こちらをご参考ください!
日別訪問者数の最大平均区間(paizaランク B 相当)の解答
ではここまで紹介したポイントを使って、問題を解いていきます。
入力を受け取り、リストや変数を準備する
今回の問題では
- 1行目で 半角スペース区切りで全日数とキャンペーンの日数
- 2行目で1日ごとの訪問者数
が入力されます。
そのため内包表記を使って
- 全日数とキャンペーンの日数は変数に代入
- 1日ごとの訪問者数はリストに代入
のように入力を受け取ります。
# 全日数とキャンペーンの日数の入力を受け取る total, period = [int(x) for x in input().split() ] # 1日ごとの訪問者数の入力を受け取る visitors = [int(x) for x in input().split()]
標準入力や内包表記については、こちらをご参考ください!
キャンペーンの候補数と最も早い開始日を求める
次に「キャンペーンの候補数と最も早い開始日を求める」についてです。
全日数をキャンペーンの日数の期間に分けて
各期間の合計訪問者数を計算します。
# "(全日数)-(キャンペーンの日数)+1"回処理を繰り返す for i in range(total - period + 1): # 各期間の合計訪問者数 sum_visit = sum(visitors[i:i+period])
そしてif elif文で条件分岐を行い
キャンペーンの候補数と最も早い開始日を求めます。
# 最大の合計訪問者数 max_visit = 0 # キャンペーン期間の候補数 count = 0 # キャンペーンの開始日 date = 0 # "(全日数)-(キャンペーンの日数)+1"回処理を繰り返す for i in range(total - period + 1): # 各期間の合計訪問者数 sum_visit = sum(visitors[i:i+period]) # これまでの最大合計訪問者数より大きい場合 if sum_visit > max_visit: # 最大の合計訪問者数を更新 max_visit = sum_visit # キャンペーン期間の候補数をリセット count = 1 # キャンペーンの開始日を更新 date = i + 1
if文については、こちらをご参考ください!
結果を出力する
最後に「結果を出力する」についてです。
今回の問題では最終的な結果として
キャンペーンの候補数と最も早い開始日を半角スペース区切りで出力します。
# キャンペーンの候補数と開始日を出力 print(count, date)
出力についてはこちらをご参考ください!
解答
全てまとめると解答は以下です。
# 全日数とキャンペーンの日数の入力を受け取る total, period = [int(x) for x in input().split() ] # 1日ごとの訪問者数の入力を受け取る visitors = [int(x) for x in input().split()] # 最大の合計訪問者数 max_visit = 0 # キャンペーン期間の候補数 count = 0 # "(全日数)-(キャンペーンの日数)+1"回処理を繰り返す for i in range(total - period + 1): # 各期間の合計訪問者数 sum_visit = sum(visitors[i:i+period]) # これまでの最大合計訪問者数より大きい場合 if sum_visit > max_visit: # 最大の合計訪問者数を更新 max_visit = sum_visit # キャンペーン期間の候補数をリセット count = 1 # キャンペーンの開始日を更新 date = i + 1 # キャンペーンの候補数と開始日を出力 print(count, date)
ぜひご参考ください!
まとめ
今回はpaizaのレベルアップ問題集の中で
- 日別訪問者数の最大平均区間: (paizaランク B 相当)
の解答と解説を紹介しました。
Bランクの問題になると、問題文が長くなり理解が難しくなります。
しかし問題を誤解していたことに後から気づいてやり直すと
大幅な時間のロスになってしまい
おそらくランクアップすることが出来ません。
まずは焦らず問題をちゃんと理解するように心がけましょう!
また他のレベルアップ問題集の問題についての解説も、ぜひご参考ください!