実用Code Golf改

実用Code Golfの続き。十進小数の小数部を二進の循環小数表現に変換するJavaScriptの関数。

職場の同僚である @Satoooooooooooo さんに、もっと短くする方法を教えてもらいました。

// 元のコード: 139文字
function(f){s="",d=Math.pow(10,f.length),a=[];while((i=a.indexOf(f*=2))<0)a.push(f),s+=f<d?0:1,f%=d;return s.slice(0,i)+"("+s.slice(i)+")"}
// 短縮版: 128文字
function(f){for(s="",d=eval("1e"+f.length),a={},j=0;!(i=a[f*=2]);a[f]=j++,s+=f/d|0,f%=d);return s.slice(0,i)+"("+s.slice(i)+")"}

工夫は次のとおりです。

配列のindexOfではなく、辞書を使う

元のコード 短縮版
初期化 a=[] a={},j=0
判定 (i=a.indexOf(f*=2))<0 !(i=a[f*=2])
インデックスの記録 a.push(f) a[f]=j++

工夫というより、辞書を使うほうが素直です。差し引き6文字の節約。

whileの代わりにforを使う

元のコード 短縮版
A;while(B)C; for(A;B;C);

CやJavaでも使える工夫です。1文字の節約。

0とのビット演算で小数部を消す

元のコード 短縮版
f<d?0:1 f/d|0

f

数値リテラルの指数表現で10nを表現する

元のコード 短縮版
Math.pow(10,f.length) eval("1e"+f.length)

数値リテラルで末尾に「e指数」をつけると、「元の数値×10指数」になります。たとえば、1e3=1000。数値リテラルを文字列で作って、evalすれば良いってわけです。

これが一番感心しました。2文字の節約。