Two Dice of A sides ネタばらし

anarchy golf - Two Dice of A sides
時間切れにてソース公開したのでネタばらし。
下記はぐだぐだ書いてるだけなんで、上のリンクからソース見た方がはやいっす。
最初に問題を見た日に出来たのはこんなのでした。

main(n){for(;9/printf("N=%d,A=%d\n",n++,(n>9?n/11+11:n+1)/2););}

ループの終了条件9/printf(...)を思いついたりして削った結果64バイト。そのときのトップには1バイト及ばず。
色々考えても思いつかず、変数一個には限界を感じたのでAの値をインクリメントする作戦に切り替えました。
Aの値が切り替わる条件は、

  • Nが奇数である (a)
  • Nが10以下、または11の倍数 (b)

の両方を満たすときなので、あとは両方を満たすときに1、それ以外は0となるコードを短く書けばよい。
11の倍数判定は11で割った商か剰余でやるのが正しい(はず)、ということでまずは剰余を選んでみる。
Nを11で割ると、Nが11の倍数は余りが0になる。Nが10以下なら11の倍数ではないので0にはならない。N%11とNの大小を比べるとN<11のときだけ同じ、あとは後者の方が大きくなる。
よってN%11%NはNが10以下、または11の倍数のときだけ0、あとは1以上となる。
この式さえ出来てしまえば、(a)(b)を両方満たすかどうかは、CならN%2>N%11%N、JavaならN%2>>N%11%Nと書ける。
で、最終的にぼくが出したのはこんなコード(60バイト)でした。

a;main(n){for(;9/printf("N=%d,A=%d\n",n++,a+=n%11%n<n%2););}

(サブミットしたコードとは変数名が異なっています)

いろいろな言語で出してみる

一応これでCは打ち止めかなと思ったので、他の言語で同じことをやってみることにしました。
C++

#import<ios>
int a,b;main(){for(;9/printf("N=%d,A=%d\n",a,b+=++a%11%a<a%2););}

D

void main(){for(int n,a;9/printf("N=%d,A=%d
",n,a);)a+=++n%2>n%11%n;}

Java(シフト)

class A{public static void main(String[]z){
    for(int n,a=n=0;n++<99;System.out.println("N="+n+",A="+a))
        a+=n%2>>n%11%n;
    }
}

JavaScript

for(n=a=0;n++<99;print("N="+n+",A="+a))a+=n%2>n%11%n

PHP

<?for(;$n++<99&&$a+=$n%11%$n<$n%2;)echo"N=$n,A=$a
";

Ruby(シフト)

a=0;1.upto(99){|n|puts"N=#{n},A=#{a+=n%2>>n%11%n}"}

AWK

END{for(;n++<99;)print"N="n",A="(a+=n%11%n<n%2)}

で、Perlを考えているうちに2変数にせずにminがあればいいことに気付きました。
(その後さらにC++の別解を考えてるときにgcc拡張のminと三項演算子の二項目省略に行き着きましたorz)
Cで使った方法は使えないときはminで解き、結局13言語(C,C++,D,Java,JavaScript,PHP,Ruby,Perl,Python,AWK,Lua,OCaml,Scheme)でサブミット。1/3くらいはほとんど書いたことなかった言語でした。

時間切れが来て

RubyPerlは結局一位タイになれませんでした。
Rubyはminがあること、Integer.timesの$.の存在を知らなかったです。
Perlは…未だに読めません(泣