【At Coder】ABC081B 解いてみて

初のB問題に挑戦してみました。
解いてから、もう少しA問題やっておくべきだったなと後悔。笑

https://atcoder.jp/contests/abs/tasks/abc081_b

ほぼ公式通りの回答だったかな、と思います。
ただ、別解として出されていたものをpython化するときに意外と躓いたので一応備忘録込めて書いておきます。

hakutatsuの回答

n = int(input())
list = list(map(int, input().split()))

counter = 0
b = 0

while True :
  for i in range(n):
    if list[i] % 2 == 0:
      list[i] = list[i] / 2
      if i + 1 == n:
        counter += 1
    else:
      b = 1
      break
  if b == 1:
    break

print(counter)

一応自力で解きました。。
まずinputが複数行で来るときの対応が分からなくて苦戦。

わかってしまえば何ということはなく、単に行をずらして書けばよいだけでした。

# 一行目のインプット 10
# 二行目のインプット 20

a = int(input())
b = int(input())

print(a)
# 10
print(b)
# 20

あとはwhileとforのネストでbreakさせるのにうまい方法がないか、と粘ったのですが思いつかず、結局2回書きました…
フラグを使う、という使い方自体は公式と同じだったのでちょっと安心。

フラグの命名が焦りすぎてbreakのbを取ってきたのですが、なんの変数かこれだと分からないですね。笑

別解

この記事を参考にしました。

2で割れるやつの最小値を求めれば良い、と。
ほうほう。

その考えを元に書いたのが以下。

n = int(input())
list = list(map(int, input().split()))

min = 10000

for i in range(n):
    counter = 0
    a = int(list[i])

    while a % 2 == 0:
        a = a / 2
        counter += 1

    if min > counter:
        min = counter

print(min)

こっちのほうが見た目としてはシンプルですかねー。
こういう考え方をパッとできるようになりたい。

C++の書き方だとminを別の変数に入れていたりするのですが、pythonで意味があるか掴みきれず省略。

あとはインデントの位置をそのままコピって、全然うまく行かずにハマりました。
pythonではインデントの位置変えるだけで実行内容変わっちゃうので要注意ですね。

比較

hakutatsu23ms9052KB
別解27ms9116KB

若干オリジナルの回答のほうが速度は早いみたいです。
とはいえ試行回数が増えるとコード書くのにミスが増えそうなので、別解の回答方針を知れたのは良かったと思います。

まとめ

はじめてのB問題でしたが、なんとか自力で解けてよかったです。
無駄に1時間くらい掛かりましたが、ロジックの実装というよりはpythonの記法になれてない、というところも正直多いかなと。

もう少し基礎固めをしないと、今後の難しい問題には太刀打ちでき無さそうですね。
ということで、しばらくはA問題を漁って解いてみたいと思います。

おすすめの記事