JavaScriptで文字数を削減する11のポイント
じつは今回のコードゴルフ問題、
それはどこでしょうか?
その答えはメインディッシュとして後に置いておき、
文字数を削減すると、
ポイントは以下の11個です。
その1 動作に影響しない文字を削る
具体的には以下がポイントです。
- 変数宣言のvarを削る
(ただし、 再帰関数内の変数は変数宣言が必要なので注意) - 無駄なスペースやタブ文字、
改行や末尾のセミコロンは削除する - 変数名は1文字にする
var res = "";
↓
r=""
その2 配列は[]で初期化し、要素数は指定しない
JavaScriptは、
maze = new Array(w * h);
↓
m=[]
その3 for文の棘括弧({})を削り、処理はカンマで連結する
for (~) {
処理1
処理2
}
↓
for(~)処理1,処理2
その4 if文を条件演算子にする
if (maze[x + w * y] == 1) {
res += "■";
} else {
res += " ";
}
↓
res+=maze[x+w*y]==1?"■":" "
その5 文字列内の特定の1文字は添え字で取得する
res+=maze[x+w*y]==1?"■":" "
↓
res+=" ■"[maze[x+w*y]]
その6 booleanは数値演算する(0,1になる)
console.log(0+true) // 1と出力
その7 |0で整数を表現する
console.log(2.345|0) // 2と出力
その8 0をfalseの代わりに、0以外をtrueの代わりに使う
for(i=10;i--;)console.log(i); // 9~0が出力
その9 空文字を数値演算で0にする
i="";console.log(++i); // 1と出力
i="";console.log(i++); // 0と出力
i="";console.log(i); // 空文字が出力
その10 要素数1の配列は中身をそのまま使う
i=[100];console.log(++i); // 101と出力
i=[100];console.log(i++); // 100と出力
i=[100];console.log(i); // [100]が出力
i=[];console.log(++i); // 1と出力
i=[];console.log(i++); // 0と出力
i=[];console.log(i); // []が出力
その11 変数を初期化する場所を変える
// 初期化
i=[j=9,k=l=((m=8)/2)]
// 出力
console.log("i=" + i); // i=9,4と出力
console.log("j=" + j); // j=9と出力
console.log("k=" + k); // k=4と出力
console.log("l=" + l); // l=4と出力
console.log("m=" + m); // m=8と出力
肝は「規則正しいデータを、プログラムで再現するコードを書けるかどうか」
それではいよいよ、
この問題には、
それでは、
プログラムを見た瞬間に、
以下、
その1 スペース、タブ文字、改行を削る
p=[[0,1,2,3],[0,1,3,2],[0,2,1,3],[0,2,3,1],[0,3,1,2],[0,3,2,1],[1,0,2,3],[1,0,3,2],[1,2,0,3],[1,2,3,0],[1,3,0,2],[1,3,2,0],[2,0,1,3],[2,0,3,1],[2,1,0,3],[2,1,3,0],[2,3,0,1],[2,3,1,0],[3,0,1,2],[3,0,2,1],[3,1,0,2],[3,1,2,0],[3,2,0,1],[3,2,1,0]];
実は、
その2 1次元配列化する
p=[0,1,2,3,0,1,3,2,0,2,1,3,0,2,3,1,0,3,1,2,0,3,2,1,1,0,2,3,1,0,3,2,1,2,0,3,1,2,3,0,1,3,0,2,1,3,2,0,2,0,1,3,2,0,3,1,2,1,0,3,2,1,3,0,2,3,0,1,2,3,1,0,3,0,1,2,3,0,2,1,3,1,0,2,3,1,2,0,3,2,0,1,3,2,1,0];
配列が文字数を削減すべきポイントだと気づいています。しかし、
その3 文字列化する
p="012301320213023103120321102310321203123013021320201320312103213023012310301230213102312032013210";
これで文字数が一気に半減しました。文字列の添え字で特定の文字列を取得すれば、
文字列化については、
まず、
似た手法として、
しかし、
その4 計算で取得する
これが本命です。
patternの値は、
「規則正しいデータを、
それが、
以下、
dir = [[-1, 0], [0, -1], [1, 0], [0, 1]]
x = 50;
y = 4;
d = dir.concat();
for (var i = 0, o=24; i < 4; i ++) {
v = d.splice((x+3)*(y+5)*7%o/(o=o+3>>2), 1)[0];
console.log(v)
}
[-1, 0]
[1, 0]
[0, 1]
[0, -1]
うまく書けば、
また、
[[-1, 0], [0, -1], [1, 0], [0, 1]]
も、
[1,w,-1,-w]
上位者はどのようなコードを書いたか
今回の問題はコードゴルフの問題でもありながら、
最後に、
3位(208文字)sapics様のコード
for(var i=w=56,j=24,l=[1,w,-1,-w],q=this.p||(m=[],i*=35,500);i;s=m[i+225]=" ■\n"[i--%w?i%w%54>0&i/w%34>1:2])i<5&&m[p=q-2*l.splice(~q%w*~(q/w)*7%j/(j/=i),1)]<s&&yourCode(m[p]=m[p+q>>1]=s);return m.join("")
計算を簡略化するには、
また、
2位(207文字)hogeover30様のコード
for(x=r="",y=w=56;x<y+w;y<1904?f[++y]=y%w>2:r+=" ■\n"[++x%w?f(276)|f[x+1]:2]);function f(z,o,p){for(p=[1,w,-1,-w],o=24;d=-p.splice(~z%w*~(z/w+4)*7%o/(o=o+3>>2),1);)f[a=z+2*d]&&f(a,f[a]=f[a-d]=0)}return r
「function f」
f[++y]
のように、
1位(206文字)iehn様のコード
for(var z=o,a=1964,d=[1,w=56,-1,-w],i=5;a--;i?b||yourCode(m[o]=m[o+z>>1]=1):d+=" ■\n"[!p+b])o=i?z+d.splice((z%w*7+2)*(0|z/w+9)/(--i>3?6:i-1)%i,1)*2:a,b=(p=o%w)>54|p<2|o>w*34|o<w|m[o];return d}o=1685,m={
「プレイグラウンド上でコードをevalで動かしている」
まず、
「コードを削る」
ぜひ、