(シングル|ダブル)クォーテーションはいらない

PHPゴルフにも細かいテクニックみたいなものはいくつかありますが,これが一番大事なのでそれっぽいタイトルをつけました.他のことは知らなくても,それほど問題ないです.

ゴルフ場ではどこでもE_NOTICEレベルのエラーは出力されないようになっています.つまりFizzBuzzを出力したかったら
<? echo "FizzBuzz";

とする必要はなく

<? echo FizzBuzz;
で良いということです.もちろんFizzBuzzなる定数が定義されていたらそちらが出力されます.

ということで,アルファベットは引用符で囲わないでも良いことがわかりました.もちろん数字も同様です.残るは記号や改行コードですが,これも上記の応用で引用符を回避できます.

どういうことか?zero linesを例に考えてみます.
問題を説明すると,入力が与えられて,改行コード以外の文字を数字の0に変換する問題です.
普通に書くと

<?=preg_replace('/./',0,fread(STDIN,1e5));
とかなります.これを引用符なしで書くと
<?=preg_replace(~ミムミ,0,fread(STDIN,1e5));
となります.文字コードはSJISを想定しています.

どういう仕組かというと,まずチルダ演算子はビット反転する演算子です.数字だけでなく文字列もビット反転できます.次に,スラッシュのアスキーコードは47(\x2f)です.これをビット反転すると208(\xd0)になります.SJISで208に該当する文字は半角カナのミですので,これを反転させたのがスラッシュになるということです.ミムミを引用符で囲わないでもエラーにならない理由は,ミムミが定数として許されている文字列だからです.PHPマニュアルにも,有効な定数の名前は、[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*と記載されています.

fatal error で終了

zero linesには続きがありまして,上記が最短解ではありません.ToastyXさんが初めて使用した「エラーで終了」というテクニックが使われています.コードを見てみましょう.

<?for(;;)echo@~fgetc(STDIN)^\xc5?0:~\xf5;
\xc5はSJISで「ナ」です.\xf5は対応する文字が無いので,このまま書いていますが1byteの文字です.

for文の条件部分がありませんが,ちゃんと停止します.標準入力の最後まで読み込むとfgetc(STDIN)はNULLを返しますが,NULLをbit反転しようとするとfatal errorが発生してスクリプトは停止します.もちろんそのままだと,標準出力にエラー文が出てしまうので,@で消しています.

echo 以降の部分も解説すると ~fgetc(STDIN)^\xc5の部分で改行コードかそれ以外か判定しています.^はxorを取る演算子で,入力がLFの場合は LF(\x0a)をビット反転した\xf5と\xc5のxorを取ることにより\x30(数字の0)を得ています.PHPの文字列は0だけfalseと判定され,それ以外はtrueなので,上記のコードは「LFなら~\xf5(つまりLF),それ以外なら0」という意味になります.



編集中・・・・わかりにくいので,あとで手直しします.
そもそも\x**って何?って方は http://d.hatena.ne.jp/milieu/20100702 を見てください.少しはわかるかもしれません.

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

メンバーのみ編集できます