問題の概要
三進法の特殊な例として、2を-1として扱う平衡三進法で任意の数を表せという問題です。
例えば表したい数値が2であれば2=3+(-1)なので12となり、7であれば7=3^2+(-3)+1なので121です。一見、負数を使っていることから表し方が一意に定まらないようにも見えますが、実はこの方法で任意の整数を一意に表すことができます。
実際のコード
t=lambda n=int(input()):[t(n//3)+"0",t(~-n//3)+"1",t(-~n//3)+"2"][n%3]if-~n//3 else str(n%3)
print(t())
ワンライナーで見づらいので成形します。
t=lambda n=int(input()):
[t(n//3)+"0",t(~-n//3)+"1",t(-~n//3)+"2"][n%3]
if-~n//3
else str(n%3)
print(t())
012の文字を条件に従って再帰的にプッシュしていくというプログラムです。もっとわかりやすくすると、
def t(n):
if -~n//3:
if n%3==0:
return t(n//3)+"0"
elif n%3==1:
return t(~-n//3)+"1"
else:
return t(-~n//3)+"2"
else:
return str(n%3)
print(t(int(input())))
です。余りが2のときには結果に1を足して2をプッシュし、余りが1のときには結果から1を引いて1をプッシュします。ちなみに文字数はビット演算の方が少ないです。
ここから短くしていく作業です。余りが012の3通りしかないため、リストの012番目を参照する形にすれば、returnをリストに書き換えできます。つまりは、
def t(n):
if -~n//3:
return [t(n//3)+"0",t(~-n//3)+"1",t(-~n//3)+"2"][n%3]
else:
return str(n%3)
print(t(int(input())))
と書き換えが可能です。
あとはラムダ式を使ってif文を1行にまとめれば、1番上のコードになります。結果としては150byte程度から103byteまで短縮できました。
103byte.py
t=lambda n=int(input()):[t(n//3)+"0",t(~-n//3)+"1",t(-~n//3)+"2"][n%3]if-~n//3 else str(n%3)
print(t())
残りの短縮可能なポイントは単なる難読化になるので、これを個人的な解答として置いておきます。それでは。