どこかに Python の練習問題みたいなものがないかとネット界をウロウロしていたら、なにやら世の中には競技プログラミングなるものがあるらしい。ということで AtCoder に登録してみた。
AtCoder に登録すると、まずおすすめの10問(AtCoder Beginners Selection)なるものに導かれたのでとりあえず解いてみた。感想とともに稚拙なコードを恥を忍んで載せる。
PracticeA - Welcome to AtCoder
AtCoder で華々しいデビューと行きたいところだったがなんだこの入力は!?どうやって変数に入れればいいのだ!というレベルだったので早速ネット様のお力を借りることとなった。なるほど、入力は大体学んだ。
a = int(input()) b, c = map(int, input().split()) s = input() print("{} {}".format(a + b + c, s))
ABC086A - Product
入力を学んだ自分には楽勝だった。さすが A 問題。
a, b = map(int, input().split()) if a * b % 2 == 0: print('Even') else: print('Odd')
ABC081A - Placing Marbles
100で割って…いや10で割って…と考えれば考えるほど一生終わらない気がしたのでインターネッツで検索。文字列とみれば扱いやすく、目からうろこだった。
num = input() print(int(num[0]) + int(num[1]) + int(num[2]))
ABC081B - Shift only
これは簡単だった。ちなみに入力は手も足も出なかったので(略)。
n = int(input()) l = [int(i) for i in input().split()] count = 0 while True: # 奇数があれば表示して終わり for i in range(n): if l[i] % 2 == 1: print(count) exit(0) # 奇数要素がなければ全体を2で割る l = list(map(lambda x: x // 2, l)) count += 1
ABC087B - Coins
お金に関するアルゴリズムは苦手意識があり、考えても案の定いい手が浮かばなかったので(略)。ほう、こういう風に力押しみたいなコードでもいいのかと学んだ。
a = int(input()) # 500 b = int(input()) # 100 c = int(input()) # 50 x = int(input()) count = 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: count += 1 print(count)
ABC083B - Some Sums
桁の扱いはさっき学んだので難なくクリア。
n, a, b = map(int, input().split()) some_sums = 0 for num in range(n + 1): num_sum = 0 for s in str(num): num_sum += int(s) if a <= num_sum and num_sum <= b: some_sums += num print(some_sums)
ABC088B - Card Game for Two
降順に並べて云々。これも問題なし。
n = int(input()) a = [int(i) for i in input().split()] a.sort(reverse=True) count = 1 diff = 0 for i in a: if count % 2 == 1: diff += i else: diff -= i count += 1 print(diff)
ABC085B - Kagami Mochi
集合を使えば云々。強いぞ Python。
n = int(input()) mochi_set = set() for i in range(n): mochi_set.add(int(input())) print(len(mochi_set))
ABC085C - Otoshidama
for 文を3重にすると時間切れになったので2重にとどめるよう改善した。
n, y = map(int, input().split()) for i in range(n + 1): for j in range(n - i + 1): if 10000 * i + 5000 * j + 1000 * (n - i - j) == y: print(i, j, n - i - j) exit(0) print(-1, -1, -1)
ABC049C - 白昼夢
手も足も出なかった。『やるだけPython競プロ日誌』様の記事を見て理解。後ろから処理するのは柔軟な頭がないと思いつかないなぁと。
s = input() words = ('dream', 'dreamer', 'erase', 'eraser') while True: for word in words: if s.endswith(word): s = s[:-len(word)] break else: print('NO') break if not s: print('YES') break
ABC086C - Traveling
満を持しての最終問題だったがどうしてもテストケースの after_contest_01.txt だけが通らなかった。
n = int(input()) txy_list = [] for i in range(n): txy_list.append([int(i) for i in input().split()]) for i in range(n): t, x, y = txy_list[i] if (x + y) > t or t % 2 != (x + y) % 2: print('No') exit(0) elif i != n - 1: txy_list[i+1][0] -= t txy_list[i+1][1] -= x txy_list[i+1][2] -= y print('Yes')
感想
10問解き終わっての感想であるが、A、B 問題くらいなら日頃の頭の体操みたいなノリでやってもいいのかなと思った。高望みは挫折への早道なので地道に楽しみながらやっていければと思う。
あと、特に「ABC049C - 白昼夢」の解答を見ながら思ったのが、一般性?汎用性?はあまり求められていないのかなということである。白昼夢に出てくるのは dream、dreamer、erase、eraser という単語だったが、この問題を解くときは当然ながらこの4単語に特化したコードを書けばよいのである。これをほかの単語に置き換えても融通の利くコードを、というのは考えがちであるが競技プログラミングにおいてはあまりそういうのは求められていないような気がした。そういう点では今まで書いていたコードとは違った新鮮さを感じることができた。
限られた時間で問題を解くときはコメントも書かないかもしれないし、可読性を無視した速度重視のコードを書くこともあるだろう。「上」を目指す際にはこれまたいろいろなものを捨てる覚悟がいるのかもしれない。