intime o'

図々しい奴だけが成功者になれる (覚書より)
anarchy golf 5/14-21 2012/06/03(Sun.)
5/14
Plus insert, Make menu - anarchy golf (JavaScript)

http://golf.shinh.org/p.rb?Plus+insert
あなごるを久々にやってる.
全然テクニックが無いので全然だけど,皆が44Bとかいってる中で
私は48Bとか行って,もちろんこの4Bを減らすのに皆努力してるわけ
だけど,数字だけ見れば全然戦えてるように見えてしまうので
モチベーションが維持できる.初心者はまず洗礼を受けるような
協議はよくないよ.私はすぐに凹んで二度とやる気を起こさなくなる.

だからチェスなんてやめて麻雀とドミニオンが楽しいんだね.

主にjavascriptであって,たまにC#でも書いてるけど,これは
使ってる人がほとんどいなくて,言語の性質上,他の言語よりも
短く書くことがほとんどムリだからだろうけど,ただ私はその
言語自体の練習の目的で書いてる.

問題には他の人がsubmitしたコードを後から見ることが出来るタイプと
できないタイプがあるけど,出来るタイプのばかりのに参戦して,
とにかく他人の技を盗むことにした.
というわけでメモしよう.

数字が入った文字列を数値にキャストするには eval() もあるけど,
ただ本当に数字が入っているだけならば
var a = "123";
a = +a;
これがいい.単行演算子の+であろう.
a = -a;
だとマイナスになってしまうけど数値である.
*, /だと
a = a * 1;
a = a / 1;
という風に例えば1という定数が必要になる.

2つの数字が入った文字列を同時に数値にするにはしかし,
var a = "123", b = "456";
a + b;
これはもちろん"123456"となってしまって
先ほどのやり方を使えば,
+a+(+b)
これは問題ないが,
+a++b
これはsyntax error.
バイト数で考えるのだから下が正解だろう.
+a+b*1

変数が3つ以上ならば,最初の一つだけ単項演算子であって,
後は全部*1とする.本当の正解は,どうせその数字は入力からの
ものなのだから,初めに数値にキャストするのが良くて

var a = +readline();

これは二度と,私は忘れない.一度見れば当然すぎるやり方を
まるで思いつかなかった!

anarchy golfのjavascript処理系はSpiderMonkeyであって(バージョンはどっかに
書いてた)
入出力はreadline()とprint()で,他にあるのか無いようだけど???

二度以上printを使うならば
var p = print();
p("test");
のようにできたほうが良い.
それはもちろん,
(p=print)(1);p(2)
のように使うのである.

しかし通常はこれだと
p is undefined
とエラーが出る.

nnさんのコードを拝見すると(http://golf.shinh.org/reveal.rb?Plus+insert/nn_1335766496&js)
for(;;){}
の()の中でgcという変数にprintを代入してgc()と利用している.

gcっていうのは前から見てたんだけど何なのだろう.組み込み変数らしいけど.

さて次にclockさんのコードを拝見すると(http://golf.shinh.org/reveal.rb?Plus+insert/clock_1335779757&js)
readline()
の引数として
p = print
という代入を行なっている.

試しにこんなコードをsubmit
readline(p=print);
p(1);
確かにprint(1)された.

どうせあなごるの大抵の問題にはreadline()とprint()の両方を使うのだから,
これは必須の知識だ.逆にどうして他の人はこれを使わなかったのかな.

先ほどのnnさんのコードに戻るとforループの中で変数itを使っている.
他の人は初期化式に0で初期化するような変数を定義していたが,
このかたは定義と初期化を飛ばしてitという変数を利用している.
これもSpiderMonkeyに依る何か組み込み変数なのだろうか.
変数名がニ文字なので少し考える必要はあるけれど.

http://golf.shinh.org/p.rb?Make+menu

この問題.
for(c in readline())
が出来なくて困ってたけど,
for each(c in readline())
って書くのだった.こんなの初めて知ったが.

------------
5/17
http://golf.shinh.org/p.rb?Rotation
javascriptでまた挑戦した.
これは締め切りなし,公開なし.
自分はこれで127Bまで行ったけど限界.

# use recrusion
// 143 B
function f(a,b,c){if(b[1]==0)p(a),p(b),p(c);else f(b[0]+a[0]+a[1],c[0]+~-b[1]+a[2],c[1]+c[2]+b[2]);}while(a=(r=readline)(p=print))f(a,r(),r());

↓↓↓
function f(a,b,c){
    if(b[1]==0)p(a),p(b),p(c);
    else f(b[0]+a[0]+a[1],c[0]+~-b[1]+a[2],c[1]+c[2]+b[2]);
}
while(a=(r=readline)(p=print))f(a,r(),r());


#not use function (for-loop)
// 131 B
for(;c=(r=readline)(b=r(a=r(p=print)));p(a),p(b),p(c))for(;b[1]!=0;a=d,b=e,c=f)d=b[0]+a[0]+a[1],e=c[0]+~-b[1]+a[2],f=c[1]+c[2]+b[2]

再帰を使わないとa,b,cを一旦違う変数に代入してから更新しないといけない.
それでもfunctionを使って短く書ける技術が無いのか場面が悪いのかやっぱり
forで回したほうが短い.cのアップデートはfに代入しなくてもいいことに気づいて

for(;c=(r=readline)(b=r(a=r(p=print)));p(a),p(b),p(c))for(;b[1]!=0;a=d,b=e)d=b[0]+a[0]+a[1],e=c[0]+~-b[1]+a[2],c=c[1]+c[2]+b[2]
これで127B.

自分が見た時(上のをsubmitした直後)のJavaScriptでのランキングは
JavaScript _
Rank	User	Size	Time	Date	Statistics
1	nn	107	0.1014	12/05/13 23:44:54	0B / 57B / 50B
2	clock	115	0.0685	12/04/16 09:22:54	0B / 54B / 61B
3	rem	127	0.0866	12/05/17 02:56:25	0B / 60B / 67B
4	0mg	196	0.1579	12/04/17 18:40:00	0B / 99B / 94B

それはそうと
vi _
Rank	User	Size	Time	Date	Statistics
1	clock	39	0.1513	12/04/18 09:46:39	1B / 25B / 12B
これがすごすぎるんですけど.
自分もvi,というかvimを使ってるけど何が何だかわからない.
GolfScriptが36Bだから,ほんとにすごい.
----------
5/26
最近ちょっとやってなかった.
一時期は一日少なくともひとつ解こうとすうら思ってくらいなのに.

Number in number (http://golf.shinh.org/p.rb?Number+in+number)

文字列をそのまま文字列とするもの
for(;a=readline(p=print);) {
    if(a.length<8)a="0"+a;p(a[2]+a[3]+" "+a[6]+a[7]+" "+a[0]+a[1]+" "+a[4]+a[5]);
}
例えばaは7桁にも6桁にもなりうるのでこれはいけない.
頭にゼロを加えればいいが,出力については逆に頭のゼロを取り除く必要がない.

一方数値としてMath演算で書いたものは本質的に正しいし,何よりラクだし,こちらのほうが良いかもしれない.

for(;a=readline(p=print);) {
    p(Math.floor(a/10000%100), Math.floor(a%100), Math.floor(a/1000000), Math.floor(a/100%100));
}

清書したのが

for(;a=readline();) {
    print(Math.floor(a/10000%100), Math.floor(a%100), Math.floor(a/1000000), Math.floor(a/100%100));
}

114B
for(;a=readline();)print(Math.floor(a/10000%100), Math.floor(a%100), Math.floor(a/1000000), Math.floor(a/100%100))

a=+readline()
とすればその場で文字列から数値へキャスト出来るというついこないだ
覚えたばかりの技巧を用いようとしたが,試しに文字列のままでも通った.
div演算を使ってるのだから当然だ.
printも一度しか使っていないのだから(p=print)なんて技は必要がなかった.
あとは反復して使用されているMath.floorと大きな数値をどうにかしてまとめて
あげよう.

for(;a=readline();) {
    print(Math.floor(a/10000%100), Math.floor(a%100), Math.floor(a/1000000), Math.floor(a/100%100));
}

つまり,こう
for(;a=readline(f=Math.floor);) {
    print(f(a/10000%100), f(a%100), f(a/1000000), f(a/100%100));
}
書かざるを得ないような括弧,ここではreadlineへ渡すユニットの中で
Math.floorをfに代入してこれを用いるのが一番良い.きっと常識のはず.
ていうかそこでなくても,forの初期化式として書いてもいいか.
c=100を初期化式として宣言してこれを用いよう


100だけでなく10000くらいも代入して用いたらどうか.
あるいは10だけで戦うのはどうか
全通りは試していないが,長くなりそうだ.
少なくとも%は*よりずっと弱い結合力であるので括弧で括ったりする必要が
生じそうだし...

結局今までので

// 83B
for(c=100;a=readline(f=Math.floor);)print(f(a/c/c%c), f(a%c), f(a/c/c/c), f(a/c%c))

となっている.(5/26 15:59)
JavaScriptにおけるランキングは
Rank	User	Size	Time	Date	Statistics
1	clock	60	0.0468	12/05/24 23:57:34	0B / 37B / 23B
2	nn	60	0.0248	12/05/24 23:59:28	0B / 38B / 22B
であって,私は最下位.
公開されるのは6/7.
それまでにせめて60代には行かないとここに載っているのが
恥ずかしくて,そういうのがあって名前が未だにこんなテキトーにつけた
ペンネームなのだ.

と思いつつ改めて見てたら,カンマの後の半角空白を削り忘れていた.

// 80B
for(c=100;a=readline(f=Math.floor);)print(f(a/c/c%c),f(a%c),f(a/c/c/c),f(a/c%c))

やはり根本的にアルゴリズムが違いそうだ.
でも面倒だからこの手法におけるショーテストを目指そうか.
もう少し眺めているとそうだ(a/c)も何度も出ていることに気づいた.

for(c=100;a=readline(f=Math.floor);)print(f(a/c/c%c),f(a%c),f(a/c/c/c),f(a/c%c)) // 比較対象
for(c=100;a=readline(f=Math.floor);)print(f((b=a/c)/c%c),f(a%c),f(b/c/c),f(b%c))
for(c=100;a=readline(f=Math.floor);)print(f((b=a/c/c)%c),f(a%c),f(b/c),f(a/c%c))
念の為(a/c/c)を纏めるのも書いたけど見事に全て同じ長さでしたね.
しかもこれはさらに長くなった.
for(c=100;a=readline(f=Math.floor);)print(f((d=(b=a/c)/c)%c),f(a%c),f(d/c),f(b%c))

コメ(0) | トラ(0)