こんにちは masa (@masa141421356)です。
竹迫さんのPythonのネタを見てVB.NETでも "saru"を記号だけで出力できるつぶやいたところ
意外と反響があったので記事を書いてみました。よろしくおねがいします。
VB.NETは言語仕様上普通の方法では記号だけでプログラムを記述する方法がありません。
しかし、VB.NETのイミディエイトウィンドには古いBASICでPRINT文のエイリアスとして用意されていた
? expression
が今でも
Debug.Print(expression)
のエイリアスに形を変えて生き残っているので、これを使って記号だけでコードを実行させることにします。
VB.NETの構文では記号だけを使って記述できるリテラルは文字列だけなので、それを使って何とかして英数字
を作る方法を考えます。
&演算子は文字列と文字列ではない値の組み合わせの場合は、自動的に一方の値を文字列へ変換します。
つまり、
?"" & (式)
を
?(式).ToString()
の代わりに使用することが可能です。
文字列と文字列の比較の結果はBooleanになるので、これを利用して値の文字列表現を得ることが出来ます
""&(""="") → "" & True → "True" ""&("">"") → "" & False → "False"
+ - * / ^ 等の数値演算の演算子と Boolean を組み合わせて使うと True は -1, False は 0
として計算が行われるので、これを使用していろいろな数値を生成することが可能です。
?-("">"") → 0 ?-(""="") → 1 ?-(""="")-(""="") → 2
生成した数値を "" と&演算子で結合することで、"0"~"9"の数字が生成できます。
文字列(整数)
を使うと
文字列.charAt(整数)
と同じ様に指定位置の文字を切り出すことが可能なので、これを使って
?(""&("">""))(-(""="")-(""="")-(""="")) → ("" & False)(-True-True-True) → "False"(3) → "s"c
の様にして "True", "False" に含まれる "a", "e", "F", "l", "r", "s", "T", "u" を切り出すことが出来ます
ここまで説明した内容を組み合わせると "saru" を作ることが可能です。
"saru" = "False"(3) & "False"(1) & "True"(1) & "True"(2)
なので
?(""&("">""))(-(""="")-(""="")-(""=""))&(""&("">""))(-(""=""))&(""&(""=""))(-(""=""))&(""&(""=""))(-(""="")-(""="")) → "saru"
となります。
0/0 が NaN になることを利用して
?("" & ((""="")/(""="")))(-("">"")) → "N"
で "N" を生成することが可能です。また、大きな数値の文字列表現が指数表示になることを利用すると "E" も生成することが可能です。
1/0 の文字列表現から "Infinitiy" が取れそうなのですが、残念ながら無限大の文字列表現は "∞"
になってしまうので英数字の取り出しには使用できません。