こんにちは、こんぶちゃ(茶コーダー)です!
初心者視点から競プロAtCoderのABC327のA問題〜C問題の自身の解答と解答説明をしていきます。
まだまだ学習の身ですので、最適コードではない部分も多々あるかと思いますが、その部分は同じ学習者として温かい気持ちで応援&ご助言頂けば嬉しいです。
では早速行ってみましょう!
今回の参加コンテスト(ABC327)
A問題:ab
問題(要約)
与えられた英小文字からなる文字列Sにおいて、文字aと文字bが隣接している箇所が存在するかどうかを判定することです。隣接している箇所があればYes、なければNoを出力する必要があります。順序は問いません。
解答
# 入力を受け取る
n = int(input()) # 文字列の長さ
S = input() # 文字列
# 文字列を走査して隣接する'a'と'b'のペアを探す
for i in range(n):
# 'a'と'b'の隣接をチェック(順序は問わない)
if S[i] == 'a' and i + 1 < n:
if S[i + 1] == 'b':
# 隣接する'a'と'b'が見つかればYesを出力してプログラムを終了
exit(print('Yes'))
elif S[i] == 'b' and i + 1 < n:
if S[i + 1] == 'a':
# 隣接する'b'と'a'が見つかればYesを出力してプログラムを終了
exit(print('Yes'))
# 隣接する'a'と'b'が見つからなかった場合はNoを出力
print('No')
解き方)
- 文字列Sの長さnを受け取ります。
- 文字列Sを受け取ります。
- 文字列Sを先頭から順に1文字ずつ走査します。
- 走査中の文字が’a’の場合、その次の文字が’b’であれば、’a’と’b’が隣接しているので、’Yes’を出力してプログラムを終了します。
- 走査中の文字が’b’の場合、その次の文字が’a’であれば、’b’と’a’が隣接しているので、同様に’Yes’を出力してプログラムを終了します。
- 上記のいずれの条件にも当てはまらない場合、つまり、’a’と’b’の隣接が見つからなかった場合、’No’を出力します。
B問題:326-like Numbers
問題(要約)
整数 B が与えられます。
AA=B であるような正の整数 A が存在するならばその値を、存在しないならば -1
を出力してください。
解答
# 整数Bを入力として受け取る
b = int(input())
# 正の整数Aを1から順に増やして探索
a = 1
while a ** a <= b:
# AのB乗がBと等しい場合、Aを出力してプログラムを終了
if a ** a == b:
exit(print(a))
a += 1
# AのB乗がBと等しい場合が見つからなかった場合、-1を出力
print(-1)
以下詳細
- 整数Bを入力として受け取ります。
- 正の整数Aを1から順に増やしながら以下の処理を行います。
- AのB乗を計算し、計算結果がBと等しい場合、Aの値を出力してプログラムを終了します。
- 上記の条件に当てはまらない場合、Aを1増やして次の値での計算を行います。
- Aの値がBの平方根(A ** A <= B)を超えるまで繰り返します。
- 上記のループを抜けた場合、AのB乗がBと等しい場合が見つからなかったことを意味し、-1を出力します。
C問題:Peak
問題(要約)
9×9のマス目Aが与えられ、各マスには1以上9以下の整数が書き込まれています。条件を満たすかどうかを判定してください。条件は以下の通りです:
- Aの各行について、その行に含まれる9マスには1以上9以下の整数がちょうど1個ずつ書き込まれている。
- Aの各列について、その列に含まれる9マスには1以上9以下の整数がちょうど1個ずつ書き込まれている。
- Aの行を上から3行ずつ3つに分け、同様に列も左から3列ずつ3つに分けたとき、それぞれの3×3のマス目には1以上9以下の整数がちょうど1個ずつ書き込まれている。
これらの条件をすべて満たしている場合に”Yes”、満たしていない場合に”No”を出力してください。
解答
各列、各行、各3x3ブロックをそれぞれ順番に調べていく(全探索)。
# 9x9のマス目Aを入力として受け取る
A = [list(map(int, input().split())) for _ in range(9)]
# 各行について、1から9までの数字が1回ずつ出現しているかをチェック
for i in range(9):
numbers = [0] * 9 # 各数字が出現したかどうかを示すリスト(初期値は0)
for j in range(9):
numbers[A[i][j] - 1] = 1 # 出現した数字に対応するインデックスを1に変更
if sum(numbers) != 9:
# 1から9までの数字が1回ずつ出現していない場合、'No'を出力してプログラムを終了
exit(print('No'))
# 各列について、1から9までの数字が1回ずつ出現しているかをチェック
for j in range(9):
numbers = [0] * 9
for i in range(9):
numbers[A[i][j] - 1] = 1
if sum(numbers) != 9:
exit(print('No'))
# 3x3の各ブロックについて、1から9までの数字が1回ずつ出現しているかをチェック
for k in range(0, 9, 3):
for l in range(0, 9, 3):
numbers = [0] * 9
for i in range(k, k + 3):
for j in range(l, l + 3):
numbers[A[i][j] - 1] = 1
if sum(numbers) != 9:
exit(print('No'))
# すべての条件を満たしている場合、'Yes'を出力
print('Yes')
解き方)
- 各行のチェック: 各行について、1から9までの数字が1回ずつ出現していることを確認します。各行の数字をリストで管理し、そのリスト内で1から9までの数字がそれぞれ1回ずつ出現していることをチェックします。もし1から9までの数字が1回ずつ出現していない場合、’No’を出力してプログラムを終了します。
- 各列のチェック: 同様に、各列についても1から9までの数字が1回ずつ出現していることを確認します。各列の数字をリストで管理し、同様にチェックを行います。もし1から9までの数字が1回ずつ出現していない場合、’No’を出力してプログラムを終了します。
- 各3×3ブロックのチェック: マス目を3×3のブロックに分けて、それぞれのブロックについて1から9までの数字が1回ずつ出現していることを確認します。各ブロック内の数字をリストで管理し、同様にチェックを行います。もし1から9までの数字が1回ずつ出現していない場合、’No’を出力してプログラムを終了します。
感想
今週もC問題まで解けました!最近、安定して嬉しいです !^^!
A問題は、if文を使って、文字列の範囲に気をつけながらコードを提出・・・不正解。楽勝と思っていたので、焦りました。文字列の範囲が正しく設定できていなかったため、修正して正解になりました。気を抜かないことが大切と学びました。
B問題は、制約の数までfor文を回せば解ける!っと思ったのですが、for文をいくつまで回すのかすぐに出てこず(数学の知識不足です)・・・。方針を変えて、while文で対応しました。過去の自分でしたら、for文にこだわって時間をロスしていました。繰り返しが対応力の向上ですね。
C問題は、全検索ですべてのパターンをfor文で実装しました。全検索は慣れてきましたので、時間も早めに解くことができました^^ スムーズに解けたことで、全検索の実装に更に自信がつきました。
この後、D問題に挑戦し、DFSで解けないかを試みましたが回答まで辿り着けず。回答を確認したら、二部グラフでDFSで解ける問題でした。過去に実装したことあったので、悔しかったです。
Ratingも徐々に上がり自身の最高点の566点になれました!この勢いでレベルアップを図っていきたいと思います。
それでは、良い競プロライフを~!(*^▽^)/
コメント