PHPゴルフにも細かいテクニックみたいなものはいくつかありますが,これが一番大事なのでそれっぽいタイトルをつけました.他のことは知らなくても,それほど問題ないです.
ゴルフ場ではどこでもE_NOTICEレベルのエラーは出力されないようになっています.つまりFizzBuzzを出力したかったら
とする必要はなく
ということで,アルファベットは引用符で囲わないでも良いことがわかりました.もちろん数字も同様です.残るは記号や改行コードですが,これも上記の応用で引用符を回避できます.
どういうことか?zero linesを例に考えてみます.
問題を説明すると,入力が与えられて,改行コード以外の文字を数字の0に変換する問題です.
普通に書くと
どういう仕組かというと,まずチルダ演算子はビット反転する演算子です.数字だけでなく文字列もビット反転できます.次に,スラッシュのアスキーコードは47(\x2f)です.これをビット反転すると208(\xd0)になります.SJISで208に該当する文字は半角カナのミですので,これを反転させたのがスラッシュになるということです.ミムミを引用符で囲わないでもエラーにならない理由は,ミムミが定数として許されている文字列だからです.PHPマニュアルにも,有効な定数の名前は、[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*と記載されています.
ゴルフ場ではどこでも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]*と記載されています.
zero linesには続きがありまして,上記が最短解ではありません.ToastyXさんが初めて使用した「エラーで終了」というテクニックが使われています.コードを見てみましょう.
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 を見てください.少しはわかるかもしれません.
<?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 を見てください.少しはわかるかもしれません.
コメントをかく