【ABC327】競プロのA-C問題を40代サラリーマンがPython解説!初心者にもわかりやすく

abc327 AtCoder

こんにちは、こんぶちゃ(茶コーダー)です!

初心者視点から競プロAtCoderのABC327のA問題〜C問題の自身の解答と解答説明をしていきます。

こんな人にオススメしたい
  • 競技プログラミング初心者で、問題の解き方がわからない方
  • AtCoderの公式解説は読んだが、内容が理解できなかった方
  • Pythonでの解法を知りたい方

まだまだ学習の身ですので、最適コードではない部分も多々あるかと思いますが、その部分は同じ学習者として温かい気持ちで応援&ご助言頂けば嬉しいです。

では早速行ってみましょう!

今回の参加コンテスト(ABC327)

AtCoder Beginner Contest 327

A問題:ab

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')

解き方)

  1. 文字列Sの長さnを受け取ります。
  2. 文字列Sを受け取ります。
  3. 文字列Sを先頭から順に1文字ずつ走査します。
  4. 走査中の文字が’a’の場合、その次の文字が’b’であれば、’a’と’b’が隣接しているので、’Yes’を出力してプログラムを終了します。
  5. 走査中の文字が’b’の場合、その次の文字が’a’であれば、’b’と’a’が隣接しているので、同様に’Yes’を出力してプログラムを終了します。
  6. 上記のいずれの条件にも当てはまらない場合、つまり、’a’と’b’の隣接が見つからなかった場合、’No’を出力します。

B問題:326-like Numbers

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)

以下詳細

  1. 整数Bを入力として受け取ります。
  2. 正の整数Aを1から順に増やしながら以下の処理を行います。
  3. AのB乗を計算し、計算結果がBと等しい場合、Aの値を出力してプログラムを終了します。
  4. 上記の条件に当てはまらない場合、Aを1増やして次の値での計算を行います。
  5. Aの値がBの平方根(A ** A <= B)を超えるまで繰り返します。
  6. 上記のループを抜けた場合、AのB乗がBと等しい場合が見つからなかったことを意味し、-1を出力します。

C問題:Peak

C – Peak

問題(要約)

9×9のマス目Aが与えられ、各マスには1以上9以下の整数が書き込まれています。条件を満たすかどうかを判定してください。条件は以下の通りです:

  1. Aの各行について、その行に含まれる9マスには1以上9以下の整数がちょうど1個ずつ書き込まれている。
  2. Aの各列について、その列に含まれる9マスには1以上9以下の整数がちょうど1個ずつ書き込まれている。
  3. 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. 各行のチェック: 各行について、1から9までの数字が1回ずつ出現していることを確認します。各行の数字をリストで管理し、そのリスト内で1から9までの数字がそれぞれ1回ずつ出現していることをチェックします。もし1から9までの数字が1回ずつ出現していない場合、’No’を出力してプログラムを終了します。
  2. 各列のチェック: 同様に、各列についても1から9までの数字が1回ずつ出現していることを確認します。各列の数字をリストで管理し、同様にチェックを行います。もし1から9までの数字が1回ずつ出現していない場合、’No’を出力してプログラムを終了します。
  3. 各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点になれました!この勢いでレベルアップを図っていきたいと思います。

それでは、良い競プロライフを~!(*^▽^)/

コメント

タイトルとURLをコピーしました