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
という代入を行なっている. 試しにこんなコードをsubmitreadline(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 Bfunction 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 Bfor(;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)); }
114Bfor(;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だけで戦うのはどうか 全通りは試していないが,長くなりそうだ. 少なくとも%は*よりずっと弱い結合力であるので括弧で括ったりする必要が 生じそうだし... 結局今までので // 83Bfor(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代には行かないとここに載っているのが 恥ずかしくて,そういうのがあって名前が未だにこんなテキトーにつけた ペンネームなのだ. と思いつつ改めて見てたら,カンマの後の半角空白を削り忘れていた. // 80Bfor(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)