Code golf 反省メモ(デスマコロシアム12)(Falcon)
挑戦した問題
要約
解説記事から引用します。
はじめは、aからzの文字でcodeiqに一致する文字のみを大文字に変換します。 次にaからzの文字でdpefjr(codeiqの次の文字)に一致する文字のみを大文字に変換します。 という風に、ループする度に大文字に置換する位置をずらす処理をaからzに対して22回繰り返します。
ソースコード
自分のFalcon(57)
//0.upto(571,{i=>print(chr(97-32*(82204>>(i%26-int(i/26))&&1)+i%26))}) //times(572,{i=>print(chr(97-32*(82204>>(i%26-int(i/26))&&1)+i%26))}) //times(572,{i=>>>""%(97-32*(82204>>(i%26-int(i/26))&&1)+i%26)}) //times(22,{i=>times(26,{j=>>>(c='A'/j)/-i in"CODEIQ"?c:c/32})}) times(572,{i=>>>(c='A'/(i%26))/-(i/26)in"CODEIQ"?c:c/32})
- char変数についてASCIIコードの加減算に使える"/"演算子(int->string)が独特でした。(といいつつi/26は小数なので、引数はintじゃなくてもいいのかな)
- 下記のangel様の使用されている"/="のリテラルへの適用なども試していましたが、一重ループのこの形ではコード短縮に至りませんでした。
1位の方(angel様)のFalcon(53)の吟味
for i=7 to 28:for j=0 to 25:>>"a"/=j-=32&&20551<<i>>j
- デスマコロシアム(第12回・最終回?)に参加しました - ange1のブログ より。
- 二重ループを使っている点、"CODEIQ"の包含判定に「in 文字列」でなく「十進bit列のシフト演算」を使っている点が私のコードと異なっています。
- 他に気付くのは、ループにtimes関数でなく通常のfor文を使われている点です。確かに下記のように、ループ部分を抜き出すとangel様の方法の方が短くなっています(回す範囲は微妙に違いますが。)Rubyに慣れてきたことで先入観を持ってしまっていました。
times(22,{i=>times(26,{j=>doSomething})}) for i=7 to 28:for j=0 to 25:doSomething
- 更に、-=32&&20551<<i>>jの部分も目から鱗の処理でした。下記①②だけ考えており、③は思い付けませんでした。演算子の優先順位を意識しつつ括弧を減らすのに便利そうなテクニックです。
j + 32*【0/1となる計算処理】 //① j + 【t/fとなる計算処理】?0:32 //② j + 32&&【右から6ビット目が0/1となる計算処理】 //③(※&&はビットAND)
- また細かい点ですが、以下の1バイト差も大きいです。
n<<i>>j n<<(i-j)