【python】”YNeos”の仕組みをやっと理解した

python

こんにちは、えあーです。
適当に作った画像の圧が思ったよりあって笑ってます

暇つぶしに久しぶりにAtCoderを開いて、
なんかpythonで短いコードを書く遊び(コードゴルフっていうらしいですね)をしてました。

で、AtCoderってコードのバイト数でソートが出来るので、
pythonのコードで短い順にして一番短い人を見ると、
“YNeos”」とか「“NYoe s”」とか書いてあるんですよね。

で、何ぞやって思ってたんですけどコードゴルフして遊んでたら
理解できたので備忘録も兼ねてサラッと記事にしときます。

例題

例題というほどでもないですが、
XXXがTrueなら”Yes”、Falseなら”No”を出力する」または、
YYYがTrueなら”No”、Falseなら”Yes”を出力する
という前提で以下説明します。

※False条件のほうがやりやすいこともあるので、両方準備しておきます。

仕組み

実際のコードを簡略化して書くと、だいたいこんな感じになっています。

print("YNeos"[YYY::2])
print("NYoe s"[XXX::2])

ポイントをいくつか解説。

文字列[なんか]

文字列に配列の要素番号のようなものがついている状態。
そのまま文字列から一部を抽出する方法です。

例えば”ABCDE”[2]とすれば”C”が取れます。
スライスも使えるので、”ABCDE”[1:4]とすれば”BCD”となります。

つまり”YNeos”の文字列の一部をprintする、というコードになっています。

[::2]

スライスの仕組みの一つです。
[始点:終点]となるのはよく知られていますが、
その後ろにもう一つコロンを足して値を入れることで、
いくつごとに拾うか?」を指定できます。

“ABCDE”[::2]なら、0番目、2番目、4番目が拾われるので、
“ACE”になります。

これで、”Yes”と”No”が入り混じったような文字列になっている理由はわかりました。

[YYY::2]のYYY部分

最後にYesとNoの区別法について。
スライスの始点の位置にBooleanな値が入っています。

これは、pythonにおいて、
Trueが1、Falseが0と扱われることを利用しています。

すると、Trueなら最初の文字がスキップされ、2文字目から1文字飛ばしで拾う、
Falseなら最初の文字から1文字飛ばしで拾うというコードの出来上がりです。

したがって、
print(“NYoe s”[XXX::2])であれば「XXX」がTrueのときに1,3,5文字目の「Yes」が、
Falseのときには0,2,4文字目の「No 」が出力されます。
※AtCoderでは最後にスペースがあってもACになる。

あとはXXXやYYYの条件の部分を(できるだけ短く)生成すればOKという仕組みになっています。

ちなみにFalseを使用するYYYの条件のほうが1文字短くできます。
できるならFalseに持ち込みたいですがFalseにするために2文字以上増えるならやめるべきです。

文字数比較

ということでこの記法が本当に短いのかは検討すべきなのでやります。

「XXX」は0文字で換算します。
文字数数え間違えてたらごめんなさい。

一番普通

if XXX:
    print("Yes")
else:
    print("No")

37文字。

三項演算子

C++みたいに a ? b : c とかだと文字数削減できたのになー

print("Yes" if XXX else "No")

26文字。結構減った。
「else」が前後スペースも合わせて6文字食うので痛い。

要素参照

リストを作って、Trueが1、Falseが0を利用して表示する文字列を決める方法。

print(["No","Yes"][XXX])

21文字。若干減る。
まだ人間味がある。

解説した方法

print("NYoe s"[XXX::2])

20文字。たしかに1文字短い。
なおFalseを出せるならもう1文字短くなる。

まとめ

“YNeos”とか”NYoe s”は、コードを極限まで短くしたい人が短いコードを書くための策だった。

なので普通のコーディングで使う必要は一切なし。
というか三項演算子くらいにしとかないと多分読みにくいので、
AtCoder以外では使わないほうがいいでしょう。

ということで久しぶりのプログラミング系記事でした。

コメント