PythonでAtCoder Beginners Selection 解答と感想


プログラミングを勉強してみようと思ったけど、普通にやっても続く気がしないのでゲーム感覚で競技プログラミングをやってみようと思った。
https://atcoder.jp/contests/abs


#Welcome to AtCoder
題名からして最初の一問
`input()`で入力を受け取って、`int()`で数値に変換して、`+`で足して、`print()`で出力するくらいかな。

~~~python3
A = int(input())
BC = input()
S = input()

B,C = BC.split( )

print(str(A+int(B)+int(C))+" " + S)
~~~
#Product
*Welcome* *to* *AtCoder*よりも簡単そう
算術演算子の`+`と`%`、if文が使えれば特に難しいことはないかな
ここで`map()`を覚えてコードがより短くなった

~~~python3

A,B = map(int,input().split())

if (A*B % 2) == 0:
    print("Even")
else:
    print("Odd")
~~~

#Placing Marbles
発想としては1が書かれたマスにビー玉を置くんだから出てくる数字を全部足せば良いと思った。
なので文字列を文字ごとに分割する方法を検索したら`list()`が出てきた。
**list**っていうクラスがあって、それの型コンストラクタを使うと文字ごとに分割されるらしい。
クラスとか型コンストラクタとかに関してはまだよくわかっていないから後で詳しくやりたい。

~~~python3
A,B,C = map(int,list(input()))

print(A+B+C)
~~~
#Shift only
全ての要素についてtrueかどうかを判定したいと思って調べたら`all()`と`any()`が出てきた。
`map()`を覚えて使いまくってる。ジェネレータ式というものがあるらしく、覚えたらそっちの方が簡単に書けそう。

~~~python3
input()
A = list(map(int,input().split()))

def half(n):
    return n/2
def evenJudge(n):
    return n % 2 == 0 

i = 0

while True:
    if all(list(map(evenJudge,A))):
        A = list(map(half,A))
        i = i + 1
    else:
        break

print(i)
~~~
#Coins
多重ループができれば解けるっていう問題かな。
別の場所で似たような問題を解いたことがあるけど、拡張性を考えて再起関数を使ったような記憶。
競技プログラミングでは実行速度が大事だけど、システムを作る時には拡張性や可読性を考えて作らないといけないため、どういうプログラムを書くかは考えて学んでいかないといけないと思った。

~~~python3
A = int(input())
B = int(input())
C = int(input())
X = int(input())

n=0
for i in range(A+1):
    for j in range(B+1):
        for k in range(C+1):
            if i * 500 + j * 100 + k * 50 == X:
                n = n+1

print(n)
~~~
#Some Sums
条件に沿えば足していくだけかなと
条件をどう判定するか、各桁の足し算をどう行うかが肝なのかな？
(もう少し綺麗に書けたらと思うんですけど何かありますかね)

~~~python3
N,A,B = map(int,input().split())

num = 0

for i in range(N+1):
    if A<= sum(map(int,list(str(i)))) <= B:
        num = num + i

print(num)
~~~

#Card Game for Two
`.sort()`で大きい順に並べて、偶数番目を足して奇数番目を引く(0番目から数えて)。
if文とループを使ったけどスライスっていうものがあって偶数番目だけを取り出すのは`A[::2]`、奇数番目だけを取り出すのは`A[1::2]`とすれば良いらしい。
見たことある気はするけどよくわからなかったからスルーしてた。実際に使う場面は結構ありそうだから覚えておかねば。

~~~python3
N = int(input())
A = list(map(int,input().split()))

A.sort()

point = 0

for i in range(N):
    m = A.pop()

    if i % 2 == 0:
        point +=  m
    else:
        point -=  m

print(point)
~~~

#Kagami Mochi
ソートして0番目から順番に値が大きくなっていたらカウントっていう風にした。
`set()`という型コンストラクタを使えば重複がないデータの集合ができるらしく、`len(set(D))`で良いらしい。

~~~python3
N = int(input())

D = []

for i in range(N):
    d = int(input())
    D.append(d)

D.sort()
n = 1
for i in range(N-1):
    if D[i] < D[i+1]:
        n = n + 1

print(n)
~~~

#Otoshidama
i,jが決まるとkが一意になるのに気づかずにWAを出しまくった。
ある程度のことはプログラムがやってくれるからと思って処理を短くする努力を全然していなかったかな。
あと、`return()`以外の上手いやりかたが思いつかずに関数を定義してしまったけど、普通に`exit()`を使えばよかった。
知識として聞いたことはあっても身についてないことが多いかなぁ。

~~~python3
N,Y = map(int,input().split())

def check(N,Y):
    for i in reversed(range(N+1)):
        for j in reversed(range(N+1-i)):
            k = N-i-j
            if i * 10000 + j * 5000 + k * 1000 == Y:
                return(str(i) + " " + str(j) + " " + str(k))
                
    return('-1 -1 -1')
print(check(N,Y))
~~~
#白昼夢
前から一致している文字列を消していけば良いかと思ったが、dreamerとdreameraseの見分けがつかなくて前からだと厳しそう。後ろからやっていけば良いのではと考える。
結果ゴリ押し感が否めない拡張性皆無の見にくいソースが出来上がってしまった。
調べてみると指定文字列で終了するか調べる`.endswith()`というものがあったため、それを使えばもう少し見た目の良いソースができそう。

~~~python3
S  = input()

while len(S) != 0:
    if S[-5:] == "dream" or S[-5:] == "erase":
        S = S[:-5]
    elif S[-6:] == "eraser":
        S = S[:-6]
    elif S[-7:] == "dreamer":
        S = S[:-7]
    else:
        print("NO")
        exit()

print("YES")
~~~

####書き直し
下のように書き直してみた。最初は`.removesuffix()`を使おうとしたんだけどREが出てしまった。
この辺り原因すらよくわかってないからその辺の知識もつけていかないといけないなぁと。

~~~python3
S  = input()

while len(S) != 0:
    for removeS in ["erase","dream","eraser","dreamer"]:
        if S.endswith(removeS):
            S = S[:-len(removeS)]
            break
    else:
        print("NO")
        exit()

print("YES")
~~~
#Traveling
距離的に届くかどうかと毎秒動き続けるのでちょうどよく止まれるかどうかの2条件を確認すれば良いかなと。
同じループを2回書いてしまっているし、全部配列に入れなくても処理できるので、前の地点だけ保存しておいて、受け取ってすぐに処理するようにすればよかったと思った。

~~~python3
N = int(input())
TXY = [[0,0,0]]
for i in range(N):
    TXY.append(list(map(int,input().split())))

for i in range(N):
    if abs(TXY[i+1][2]-TXY[i][2]) + abs(TXY[i+1][1]-TXY[i][1]) <= TXY[i+1][0] - TXY[i][0]\
        and (abs(TXY[i+1][2]-TXY[i][2]) + abs(TXY[i+1][1]-TXY[i][1]))%2 == (TXY[i+1][0] - TXY[i][0]) % 2:
        continue
    else:
        print("No")
        exit()
print("Yes")
~~~

#まとめ
プログラミング言語の知識不足で色々調べなきゃいけないことは多かったが、Beginners Selectionというだけあって根本の考え方がどうしてもわからないと言ったことはなかった。
プログラム自体はそんなに時間かからずにかけたけど記事を書くのにだいぶ時間がかかってしまったなぁという感想。
記事を書く際に概念が全然理解できてないから調べて書くっていうことが多かった。（大したことは書いてないけれども）
あとは単純に日本語力がないかな・・・・
記事の書き方も書いていく上で向上していけたらなぁって感じですね。