for文とif文を1行にまとめる

1 min読了の目安(約1200字TECH技術記事

最近Atcoderを始めました。他の方のコードはとにかく短い!
今日はこちら問題を解くときにできるだけコードを短くしてみました。

https://atcoder.jp/contests/abc068/tasks/abc068_b

問題文

高橋君は 2 で割れる数が好きです。正整数 n が与えられるので、1 以上 n 以下の整数のうち、最も 2 で割れる回数が多いものを求めてください。答えは必ず 1 つに定まります。
なお、2 で割っていき、何回あまりが出ずに割れるかを、2 で割れる回数と呼ぶことにします。

入力例

15

出力例

8

8 は 3 回 2 で割ることができ、これは 1, 2, ..., 15 の中で最も多いです。

アンサー

ノーマル

まず普通に書いたコードがこちらです。

n = int(input())
x = 1
for i in range(1,7):
  if 2**i > n:
    break
  x = 2**i
print(x)

かなり簡潔にかけた気がします。
このコードを短縮系を使って書き換えてみます。

短縮バージョン

n = int(input())
x = 1
x = x if 2**i > n else 2**i for i in range(1,7)
print(x)

半分の長さになりました。
for文の4行を1行に短縮して書くこ都ができたのは、三項演算子のおかげです。

三項演算子 x for文

for i in range(1,7):
  if 2**i > n:
    break
  x = 2**i

上の4行を下の1行に書き換えました。内容が少し違うのはif 2**i > nがTrueだった場合です。

x = x if 2**i > n else 2**i for i in range(1,7)

普通に書いた方ではbreakで抜けますが、短縮版ではxにxをただ自己代入しています。
短縮版はループをフルで回す必要があるので処理速度は遅いです。

breakcontinueのような表記は式ではないので三個演算子では使えないようです。

Summary

今回のfor文とif文の組み合わせはコードを非常に短くすることができる一方でさまざまな制約があるようでした。実際に、先ほどの短縮版のコードをAtcoderで提出してみるとRuntime Errorが出てしましました。

今後も積極的に使ってみて、短縮できる場面と丁寧に書くべき場面を見極めていきます。