122333

122333 が先ほど終了した。なかなかの良問だ。おもしろかった。ただ、Sample Input #3 が、たぶん、8bit の立った右ページのコードを含んでいるようだ。そのため、Groovy では、#3 だけうまく扱えず、解答できずじまい。

C

C は 63B 出したとき、勝った!と思ったんだが、甘かった。
58B@naiさん

c;main(i){for(;read(i*=--i>-atoi(&c),&c,1);write(c!=48));}

この問題の場合、やはり、read()/write() にたどり着く。ちょっと前の、Excess3 と似たパターンだが、入力と出力が同じなので、write() を使うことで、read() との引数の同一性から、第2、第3引数を省略できる。とはいえ、こんな引数の省略なんて尋常じゃないけどな、、、、今では、みんな普通にやる定石と化している。
さて、上の nai さんの解答は、まず、write() のファイルディスクリプタに c != 48 を入れているところ、なるほど、理に適っているな。'0' 以外は出力するということだ。あとは、何回出力すれば良いかは、read() のファイルディスクリプタの値でコントロールしている。トップの hinoe さんも、同じロジックだ。

i;main(n){for(;read(i-=i+n-50<8u?:i,&n,1);)write(n!=48);}

まず、nai さんの方から行くと、atoi() は、'1'〜'9' 以外では、0 を返す。'1'〜'9' では、1〜9 を返す。read() が成功した時は、i == 0 となるので、write() を読んだ後、i がデクリメントされ、-atoi() を比較される。i は前置 -- でデクリメントされるので、c == '2'〜'9' 以外の時は、不等号が成立せず、直ちに次の文字を読みにいくことになる。read() が成功した直後に、1回は、write() しているので、それで、OK だ。c == '0' のケースだけ、write(c!=48) で無出力としている。c == '2'〜'9' の場合は、適切な回数ループするまで、i はゼロにならない。見事だな。因みに、

i*=--i>-atoi()

としていて、

i*=++i<atoi()

としていない理由は、正のファイルディスクリプタは、いくつか read() が 0 を返し、ループを抜けてしまうからだ。たとえば、

c;main(i){
    for(i=-5;i<15;i++)printf("%d %d\n",i,read(i,&c,1));
}

こんなコードを実行すると、

-5 -1
-4 -1
-3 -1
-2 -1
-1 -1
0 1
1 -1
2 -1
3 -1
4 0
5 -1
6 -1
7 0
8 0
9 0
10 0
11 0
12 0
13 0
14 0

といった感じだ。ファイルディスクリプタ 4 は本当にオープンされているのかもしれないが、7 以降はなんでなんだろう。オープンされているとは思えないが。。。
さて、話をもとに戻すと、read() のファイルディスクリプタが 0 になるタイミングをうまく調整して write() の呼ばれる回数をコントロールしているということだ。
問題の終了・公開後、hinoe さんにより、nai さんの解答ベースにした、56B がでた。以下の通りだ。

i;main(n){for(;read(i*=--i+n-49<8u,&n,1);)write(n!=48);}

nai さんの解答との違いは、数値判定法。atoi() を使わなくても、unsigned で計算することにより、あるアスキーレンジだけをうまく取り出すことができる。つまり、

n-48<10u

とやることで、n が '0'〜'9' の時のみ true となるのだ。
しかし、この問題、当初、68B あたりから戦いが始まった。よく縮まるものだ。

sed

sedもなかなか面白かった。sed の場合は、効率よく置換することで、縮まった。tails さんとは、何度か battle したが、最後は何とかトップをゲットできた。しかし、tails さんも最終的には、同率トップで、62B だが、解答は結構ちがうな。

nn:
s/0//g
s/[3569]/&&&/g
s/[478]\|99/&&&&/g
s/[268]\|55\|777/&&/g

tails:
s/[367]\|\([4-9]\)/0&&&\1/g
s/[26-9]/&&/g
s/0[579]/&&/g
s/0//g

tails さんのは、結構技巧的だな。よくこんなの思いつくな。すごい。
1.3 or 6 or 7 なら、0xxx に展開し、4 or 5 or 8 or 9 なら、0xxxx に展開する。
2.2 or 6〜9 なら、dup する。つまり、この時点で、

2 => 22
3 => 0333
4 => 04444
5 => 05555
6 => 0666666
7 => 0777777
8 => 088888888
9 => 099999999

3.次に、05 or 07 or 09 はdup する。

2 => 22
3 => 0333
4 => 04444
5 => 0505555
6 => 0666666
7 => 070777777
8 => 088888888
9 => 09099999999

4.最後に 0 を消せば、目的通りになる。
〜〜〜〜〜〜〜〜
さて、endless 問題がいくつか出題された。

sin curve

微妙。embed 解答になりそう。vi / gs はそれっぽい。

FibBuzz

FizzBuzz と Fibonacci を混ぜたもの。残念なことに、64bit では足りないので、やはり、embed となりがち。BigInteger を持つ言語は、結構簡単。

BuzzFib

こちらは、FizzBuzzFibonacci Numbers の解答を混ぜたらできあがった。ただ、C は、FizzBuzz の最短解を得ていないので、とりあえず、投稿はやめておこう。
〜〜〜〜〜〜〜〜
さて(その2)、
あなごるサーバーが引越しし、かつ、言語のバージョンがアップされた。JavaScript がちょっと影響が大きかった。というのは、かつては、RegExp の exec() 関数は、簡便に、

/foo/(s)

などと書けた。ところが、これができなくなってしまった。今後は、

/foo/.exec(s)

と書かなければならない。なんでも、かつては、

typeof /foo/ === 'function'

だったのが、

typeof /foo/ === 'object'

になったのだそうだ。ゴルフ的には残念だ。
また、SpiderMonkeyAPI で、read() が追加された。これは、ファイルを読むものだ。ただ、あまり、ファイルを読み込む問題はあなごるでは出題されていない。print fileCheck for brainwave activity などがファイルを扱う数少ない例なので、とりあえず、更新しておいた。
Groovy も 1.6 から 1.8 に上がったので、新しい機能がある。ゴルフ的には、Slashy String が使えるケースがあるかも。正規表現用の文字列構築として、

/foo bar baz/

という文字列リテラルが書けるが、これが複数行にまたがることができるようになった。つまり、

s=/foo
bar
baz/

などと書ける。そんなには有用でないかな(ゴルフ的に)。

2011/11/03 追記

JavaScript の Version Up による影響が他にもあった。かつて、文字列の長さは、

'abcdef'[-1]     // -> 6

として得られたが、これも使えなくなった。今は、undefined が返る。

'abcdef'.length     // -> 6

とする必要がある。