LoginSignup
4
1

More than 1 year has passed since last update.

AtCoder超初心者によるABC230のまとめ A~C (Python)

Last updated at Posted at 2021-12-04

ABC230

A問題

問題のイメージ

型変換を適切に行い、文字列を連結すれば解けます。

特定の文字列と標準入力の文字列を連結して出力します。

「コンテストの中止による欠番」をif文で判定し、標準入力の値を置き換える必要があります。

コード化

# 標準入力をint型で受け取る
n = int(input())

# 欠番以降は回数を1増やす
if n >= 42:
  n += 1

# 回数を3桁で揃えたときに足りない分だけ前に0を追加
# 左辺のnは文字列になる
n = "0" * (3 - len(str(n))) + str(n)

# 結合して出力
print("AGC" + n)

バグポイント

  • nを1増やすとき、nは int(n) でint型にしましょう。

  • nの文字数を len() で数えるときは str(n) でstr型にしましょう。

  • 連結の際はstr型に揃えて行いましょう。

  • print("AGC", n) とすると、出力結果にスペースが入ってしまうので、+ を用いて文字列を連結するようにしましょう。

B問題

問題のイメージ

標準入力の文字列Sが、決められた文字列Tを切り抜いた文字列になっているか判定します。

制約に「S の長さは 1 以上 10 以下である。」とあり、比較的短いことがポイントだと思います。

「文字列 T を oxx を 10^5 個結合した文字列として定めます。」
なんて書いてありますが、実際はTがそんなに長い必要はないということです。

つまり、Tの短いバージョンを準備してしまえばいいと考えました。

あとは if S in T のようにして、SがTに含まれるか判定します。

コード化

# 標準入力で文字列を受け取る
s = input()

# Tの短いバージョンを準備
t = "oxx" * 4

# SがTに含まれるか判定
if s in t:
    print("Yes")
else:
    print("No")

解説

  • "oxx" * 4 で文字列の反復を作れます。→ oxxoxxoxxoxx

  • Sは最大10文字で、以下の3通りとも oxxoxxoxxoxx の一部になっていることが分かります。つまり、Tは12文字だけ準備すれば十分だということです。

    • oxxoxxoxxo
    • xxoxxoxxox
    • xoxxoxxoxx

C問題

問題のイメージ

一見、不等式が並んでいてどんな状況なのか理解するのが難しい問題です。

私も状況理解に苦戦しました。

しかし、出力例1を見ると少しずつ理解できると思います。

出力例1
...#.
#.#..
.#...
#.#..
...#.

ポイントは3行2列めを中心に、斜めに黒く塗りつぶされていることです。

(A, B) = (3, 2) というふうに、黒の塗りつぶしが交差する場所を指定していることが分かります。

左上から右下に塗りつぶすのが「(A+k,B+k) を黒く塗る」という操作で、右上から左下に塗りつぶすのが「(A+k,B−k) を黒く塗る」という操作にあたるわけです。

出力はP行目からQ行目R列目からS列目までの範囲であることも注意が必要です。

N×Nのマス全体を再現した上で、指定された範囲を出力するというのは、実行時間的に現実的ではないと考えました。

そこで、指定された範囲の各マスが黒く塗りつぶすべきマスかどうかを判定するという仕組みで実装しました。

コード化

# N, A, Bをint型で受け取る
n, a, b = map(int, input().split())

# P, Q, R, Sをint型で受け取る
p, q, r, s = map(int, input().split())

# 出力に必要な大きさのマスを、白く塗った状態で準備する
sq = [["."] * (s - r + 1) for _ in range(q - p + 1)]

# 必要なマスを黒く塗りつぶしていく
for i in range(q - p + 1):
    for j in range(s - r + 1):

        # 中心から、傾き-1で移動した地点、または傾き1で移動した地点なら……
        if (((i + p - 1) - (a - 1)) == ((j + r - 1) - (b - 1))) or (((i + p - 1) - (a - 1)) == ((b - 1) - (j + r - 1))):
            # 黒く塗りつぶす
            sq[i][j] = "#"

    # i行目をlist形式から文字列に結合して表示
    print("".join(sq[i]))

解説

  • sq = [["."] * (s - r + 1) for _ in range(q - p + 1)] は、リスト内包表記を用いています。["."] * (s - r + 1) で一般項を書き、for _ in range(q - p + 1) で繰り返すイメージです。

  • 行方向と列方向の2つがあるのでfor文の入れ子を用いています。1行目のj文字を1文字ずつif文で確認し、2行目、3行目……とi行分繰り返すというイメージです。

バグポイント

  • 入力はすべて1から始まる整数で与えられます。つまり、例えば人間がイメージするA行目はコンピュータで言う(A-1)行目であることに注意しなければなりません。

  • j列目(j文字目)を見ているのか、i行目を見ているのか、混同しないように注意しましょう。

まとめ

アドバイスがあれば、ぜひコメントをお願いします。
次回のAtCoderも頑張りましょう。

参考

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1