ABC237参戦記

プログラミング

ABC237の参加記録です。
前回、前々回のABCがうまくいって800までもう少しまで来ました。今回のABCでパフォーマンスが1,000を超えたら、おそらくレート800を超えそうです。
レートは関係なく、楽しめたら良いな。と思いつつも、意識せずにはいられない状態で参加しました。

使用言語はPython3です。レートは800弱です。
自分が理解した内容を書いていきます。

A – Not Overflow

標準入出力と比較演算子、累乗計算(またはシフト演算子)を知っていますか。が問われる問題。

累乗の計算は、Python3では、** で書けますね。

print(2**3)
# 8

また、2の累乗の場合は、右シフト演算子 << でも同様のことができますね。

print(1<<3)
# 8

今回は、シフト演算子を利用したコードを書きました。

2の31乗した数字をXと置いて、マイナスX以上、X未満かを判定すればOKですね。
イコールを含む場合と、含まない場合に注意する必要があります。

# AtCoder Beginner Contest 237
# A - Not Overflow

N = int(input())

X = 1<<31

if -X <= N < X: # -X以上 X未満
    print("Yes")
else:
    print("No")

B – Matrix Transposition

行列の転置が書けますか。が問われる問題。

私はnumpyのT属性で取得しました。numpyの転置に関しては、ここのページがわかりやすいかと思います。

# AtCoder Beginner Contest 237
# B - Matrix Transposition

import numpy as np

H, W = map(int,input().split())
A = []

for _ in range (H):
    l = list(map(int,input().split()))
    A.append(l)

arr = np.array(A)
ans = arr.T

for row in ans:
    print(*row)

上記コードはPyPy3だとREが出るため、Python3で出す必要があります。
PyPy3ではnumpyを利用できないためですね。

このほか、zip() を利用する方法もあります。
私は、このコードは中身を理解するまでに時間がかかりました。

H, W = map(int,input().split())
A = []

for _ in range (H):
    l = list(map(int,input().split()))
    A.append(l)

for row in zip(*A):
    print(*row)

勿論、問題文にある通り、愚直に B[i][j] を A[j][i] として書き込んでしまう方法でもACします。

H, W = map(int,input().split())
A = []

for _ in range (H):
    l = list(map(int,input().split()))
    A.append(l)

B = [[None for i in range(H)] for j in range (W)]

for i in range (W):
    for j in range (H):
        B[i][j] = A[j][i]

for row in B:
    print(*row)

C – kasaka

回文判定が出来るか、場合分けを漏れなく検討できるかが問われる問題。

まず、回文判定については、入力れれる文字をSとして、以下の2パターンで判定できます。

# 回文判定1
for i in range(len(S)//2):
    if S[i] == S[-1*(i+1)]:
        continue
    else:
        print("No")
        exit()
print("Yes")
# 回文判定2
if S==S[::-1]:
    print("Yes")
else:
    print("No")

スライスを使用して、一致かどうかを判定するほうがわかりやすいと思います。
私は、コンテスト中は、for文で判定する方法で提出しました。

次に、問題文にあるように、文字列の先頭に”a”をいくつか付け加えることを考えます。
これは、末尾の”a”をいくつか取り除くことと同じ意味になりますね。
先頭と末尾に連続する”a”の個数を数えて、場合分けすると、以下の通りになります。

  1. 先頭に連続する”a”と、末尾に連続する”a”の数が同じ場合。
  2. 先頭の連続する”a”のほうが、末尾に連続する”a”よりも少ない場合。
  3. 先頭の連続する”a”のほうが、末尾に連続する”a”よりも多い場合。

1.の場合は、先頭と末尾の”a”の個数は一緒なので、そのまま回文判定すれば良いです。

2.の場合は、先頭に”a”をいくつかつけて回文判定すれば良いですね。実際には、末尾の”a”を多い分だけ取り除きました。

3.の場合は、この時点で回文ではないことがわかっていますが、そのまま回文判定しても、False として判定されます。

つまり、2.の場合だけ、追加の処理を記述すればOKになります。

あとは、回文判定して、結果を出力すればACしますね。

# AtCoder Beginner Contest 237
# C - kasaka

S = list(input())

# Sの先頭に連続して存在する"a"の数を数える
a_cnt_left = 0
for i in range (len(S)):
    if S[i] != "a":
        break
    else:
        a_cnt_left += 1

# Sの末尾に連続して存在する"a"の数を数える
a_cnt_right = 0
for i in range (len(S)):
    if S[-1*(i+1)] != "a":
        break
    else:
        a_cnt_right += 1

# 末尾の"a"の数が多い場合、同じになるまで取り除く
if a_cnt_right > a_cnt_left:
    for i in range(a_cnt_right - a_cnt_left):
        S.pop()
        
# 回文判定
if S==S[::-1]:
    print("Yes")
else:
    print("No")

私は場合分けの3.のパターンに気づかずに提出してWA出しました。

今回のコンテストでレーティング800を超えることが出来ました!
「AtCoderで緑になる。」は、昨年(2021年)の目標でした。1月遅れですがようやく達成しました。
水色目指して今後も精進していきます。

コメント

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