Cozy Ozy このページをアンテナに追加 RSSフィード

2007-11-01 もっと縮めようゼ

[][]もっと縮めようゼ もっと縮めようゼを含むブックマーク

id:haru-sさんからのトラバで知りました.

わずか565バイトテトリスのプログラミング解説

7行プログラミングですね.7行プログラミングのマインドってのは,500バイトそこそこで収まるようにソースコードを凝縮するってことだと思います.つまり制限容量に収まってしまえば,最後の詰めは甘くてもまあしかたないかなぁと私は思うのですが,まあ縮みそうなソースコードが転がっていると一応見ておきたい気もします.

とりあえず,テトリスのコードを眺めたところでは明らかに縮みそうな箇所がありますね.パッと目に付いたのは,5行目の

if(l%A)l-=l%A*!Z[l];else for(P+=k++,j=l+=A;--j>A;)

ショートコーダーはelseなんて書かないので,たとえばこんな感じで縮めてやれば良いでしょう.

for(j=l+=l%A?-l%A*!Z[l]:(P+=k++,A);l%A&&--j>A;)

3バイトほど縮みました.とはいえ,これはショートコーディングセオリーに従って単純な書き換えを行っただけです.このコードの構造を見てやると,仕方なくif文を使っているような雰囲気がありますから,真面目にアルゴリズムから考え直せばもっともっと縮むんじゃないでしょうか.興味のある人は是非チャレンジしてみてくだされ.

…というか,元のコードってキーボードの下を押しても右に移動する時があるのだけど仕様でしょうか:D

  • 追記:

上記のコードって間違ってますね^^;ソースをじっくり見ると,かなり工夫してますね.甘く見てました.とはいえ,このコードは必ず縮むと思います.

とりあえず1バイトだけ縮めました


<body onKeyDown=K=event.keyCode><script>X=[Z=[B=A=12]];h=e=K=t=P=0;function Y()
{C=[d=K-38];c=0;for(i=4;i--*K;K-13?c+=!Z[h+p+d]:c-=!Z[h+(C[i]=p*A-Math.round(p/
A)*145)])p=B[i];!t|c+4?c-4?0:h+=d:B=C;for(f=K=i=0;i<4;f+=Z[A+p])X[p=h+B[i++]]=1
if(e=!e){if(f|B){for(l=228;i--;)Z[h+B[i]]=k=1;for(B=[8-[19,32,6,-5,21,9,6][t=++
t%7],0,1,t-6?-A:-1];l--;h=5)if(l%A)l-=l%A*!Z[l];else for(P+=k++,j=l+=A;--j>A;)Z
[j]=Z[j-A]}h+=A}for(i=S="";i<240;X[i]=Z[i]|=++i%A<2|i>228)i%A?0:S+="<br>",S+=X[
i]?"■":"_";document.body.innerHTML=S+P;Z[5]||setTimeout(Y,99-P)}Y()</script>
  • さらに追記:

稲葉さんによればきっちり79文字でなくても良いみたいなので,こんな感じで簡単に短縮できますね.これで562バイト.

…って,コードサイズは改行コードを2バイトで数えるものなのかな?っちゅうか,7行プログラミングでは7行に収まってれば良いのでどうでも良いことなのかも.


<body onKeyDown=K=event.keyCode><script>X=[Z=[B=A=12]];h=e=K=t=P=0;function Y()
{C=[d=K-38];c=0;for(i=4;i--*K;c+=K-13?!Z[h+p+d]:-!Z[h+(C[i]=p*A-Math.round(p/A)
*145)])p=B[i];!t|c+4?c-4?0:h+=d:B=C;for(f=K=i=0;i<4;f+=Z[A+p])X[p=h+B[i++]]=1
if(e=!e){if(f|B){for(l=228;i--;)Z[h+B[i]]=k=1;for(B=[8-[19,32,6,-5,21,9,6][t=++
t%7],0,1,t-6?-A:-1];l--;h=5)if(l%A)l-=l%A*!Z[l];else for(P+=k++,j=l+=A;--j>A;)Z
[j]=Z[j-A]}h+=A}for(i=S="";i<240;X[i]=Z[i]|=++i%A<2|i>228)i%A?0:S+="<br>",S+=X[
i]?"■":"_";document.body.innerHTML=S+P;Z[5]||setTimeout(Y,99-P)}Y()</script>

丸め部分をMath.round使わずにやるのって,昔書いた気がするのだけど思い出せない^^;

  • さらにさらに追記:

改行位置を工夫して560バイト.改行位置を考えるってのは,Code GolfでBase64圧縮する時にやってたのを思い出しました…

<body onKeyDown=K=event.keyCode><script>X=[Z=[B=A=12]];function Y(){C=[d=K-38]
c=0;for(i=4;i--*K;c+=K-13?!Z[h+p+d]:-!Z[h+(C[i]=p*A-Math.round(p/A)*145)])p=B[i
];!t|c+4?c-4?0:h+=d:B=C;for(f=K=i=0;i<4;f+=Z[A+p])X[p=h+B[i++]]=1;if(e=!e){if(f
|B){for(l=228;i--;)Z[h+B[i]]=k=1;for(B=[8-[19,32,6,-5,21,9,6][t=++t%7],0,1,t-6?
-A:-1];l--;h=5)if(l%A)l-=l%A*!Z[l];else for(P+=k++,j=l+=A;--j>A;)Z[j]=Z[j-A]}h
+=A}for(i=S="";i<240;X[i]=Z[i]|=++i%A<2|i>228)i%A?0:S+="<br>",S+=X[i]?"■":"_"
document.body.innerHTML=S+P;Z[5]||setTimeout(Y,99-P)}Y(h=e=K=t=P=0)</script>
  • さらにさらにさらに追記

なんかこんなんみつけました.

http://blog.livedoor.jp/dankogai/archives/50941567.html

これはhtml単体で動くわけじゃないから反則っぽいけど,これを利用すると547バイト.ゴルフ的には542バイトってことですね.ちなみに↑のコードは545バイトじゃなくて547バイト(改行1バイトで552バイト,改行2バイトで558バイト)だと思います.

window.onkeydown=function(e){K=e.keyCode};X=[Z=[B=A=12]];function Y(){C=[d=K-38
]c=0;for(i=4;i--*K;c+=K-13?!Z[h+p+d]:-!Z[h+(C[i]=p*A-Math.round(p/A)*145)])p=B[
i];!t|c+4?c-4?0:h+=d:B=C;for(f=K=i=0;i<4;f+=Z[A+p])X[p=h+B[i++]]=1;if(e=!e){if(
f|B){for(l=228;i--;)Z[h+B[i]]=k=1;for(B=[8-[19,32,6,-5,21,9,6][t=++t%7],0,1,t-6
?-A:-1];l--;h=5)if(l%A)l-=l%A*!Z[l];else for(P+=k++,j=l+=A;--j>A;)Z[j]=Z[j-A]}h
+=A}for(i=S="";i<240;X[i]=Z[i]|=++i%A<2|i>228)i%A?0:S+="<br>",S+=X[i]?"■":"_"
document.body.innerHTML=S+P;Z[5]||setTimeout(Y,99-P)}Y(h=e=K=t=P=0)
  • (さらに)^4追記

ショートコーダーはelseなんて書かねーんだヨ!!の箇所を修正しました.htm単体動作版では552バイト(7行ルール&改行1バイト),ゴルフルール(改行無視)では548バイト.フォームに組み込むパターンでは541バイト.まだまだイケるハズ!

<body onKeyDown=K=event.keyCode><script>X=[Z=[B=A=12]];function Y(){C=[d=K-38]
c=0;for(i=4;i--*K;c+=K-13?!Z[h+p+d]:-!Z[h+(C[i]=p*A-Math.round(p/A)*145)])p=B[i
];!t|c+4?c-4?0:h+=d:B=C;for(f=K=i=0;i<4;f+=Z[X[p=h+B[i++]]=A+p]);if(e=!e){if(f|
B){for(l=228;i--;)Z[h+B[i]]=k=1;for(B=[8-[19,32,6,-5,21,9,6][t=++t%7],0,1,t-6?-
A:-1];l--;h=5)for(j=l+=(Q=l%A)?-l%A*!Z[l]:(P+=k++,A);!Q*j>A;)Z[--j]=Z[j-A]}h+=A
}for(i=S="";i<240;X[i]=Z[i]|=++i%A<2|i>228)i%A?0:S+="<br>",S+=X[i]?"■":"_"
document.body.innerHTML=S+P;Z[5]||setTimeout(Y,99-P)}Y(h=e=K=t=P=0)</script>
window.onkeydown=function(e){K=e.keyCode};X=[Z=[B=A=12]];function Y(){C=[d=K-38
];c=0;for(i=4;i--*K;c+=K-13?!Z[h+p+d]:-!Z[h+(C[i]=p*A-Math.round(p/A)*145)])p=B
[i];!t|c+4?c-4?0:h+=d:B=C;for(f=K=i=0;i<4;f+=Z[X[p=h+B[i++]]=A+p]);if(e=!e){if(
f|B){for(l=228;i--;)Z[h+B[i]]=k=1;for(B=[8-[19,32,6,-5,21,9,6][t=++t%7],0,1,t-6
?-A:-1];l--;h=5)for(j=l+=(Q=l%A)?-l%A*!Z[l]:(P+=k++,A);!Q*j>A;)Z[--j]=Z[j-A]}h
+=A}for(i=S="";i<240;X[i]=Z[i]|=++i%A<2|i>228)i%A?0:S+="<br>",S+=X[i]?"■":"_"
document.body.innerHTML=S+P;Z[5]||setTimeout(Y,99-P)}Y(h=e=K=t=P=0)

[]プレゼント実験(3) プレゼント実験(3)を含むブックマーク

  • 応募総数41名様,ありがとうございました

思ったよりたくさんの応募があって,驚いています.皆様どうもありがとうございました.これから抽選といきたいところですが,わざわざ「プレゼント実験」としているわけで,単純に乱数で選ぶだけはもったいない.当選するのは41名中たった3名でのこり38名の皆様にはせっかく応募してもらったのに申し訳ない.

というわけで,今朝ふと思いついたのは,今回応募してくださった方で,当選しなかった方々のメールアドレスを保存しておいて,次回のプレゼントで応募してくださった時には少し当たる確率を増やした状態で抽選するというものです.まあ,今回は皆さん1回目ということで公平にするしかないのですが….それより,第2回とかやるのかよと.

あと,募集した時(http://d.hatena.ne.jp/Ozy/20071013#p1)に

メールのSubjectは「ショートコーディング本クレクレ」でお願いしマース.

と書いているにもかかわらず全然違うタイトルで応募した方というのは,タイトルでフィルタをかけたりしたらそもそも応募していないことになってもうちょっと応募者が多いプレゼントなら確実にアウトなのですが,せっかく送ってくれたのにこれではあまりに冷たいってことで,この手のメールが来た場合は他の応募者よりも少し当たる確率を低く設定するとかやってみたいと思います.

OzyOzy 2007/11/01 18:15 しかしこんな風に書いたらlの値が変化してしまうので間違いですよね…
誰か解決して(´人`)

OzyOzy 2007/11/01 18:21 とりあえず関数呼び出しのところをY(h=e=K=t=P=0)とすればセミコロンが一つ減りますが,改行部分を固定にすると3行目がずれてしまいますねぇ.これって7行プログラミング的にはアウトなんでしょうかね.

OzyOzy 2007/11/01 19:45 単なる文字数なら簡単に縮められそうですが,改行位置まで考えると結構難しいですね.CR+LFで564バイト.皆も頑張ろう〜

shinichiro_hshinichiro_h 2007/11/01 19:53 とりあえず Math.round(p/A) => (p/A+.5|0) とか?

k.inabak.inaba 2007/11/01 20:14 79文字超えなければ(ピッタリでなくても)改行位置はずらして問題ないかと。

>キーボードの下を押しても右に は仕様と元スレに書いてありました。7行切ったら次は機能追加や使い勝手改善に走るのが7行マインドなので縮めて余ったバイト数で色々直していくと面白いと思います(^^

OzyOzy 2007/11/01 20:26 > Math.round(p/A) => (p/A+.5|0) とか?

それは試してみたんですけど,うまくいかなかったです;-;
でもこの部分は短く書けますよねー.
もうちょっと調べてみます.

> 79文字超えなければ(ピッタリでなくても)改行位置はずらして問題ないかと。

おお!それならもっと簡単に縮められますね…!!

OzyOzy 2007/11/01 21:01 (p/A|0)とすれば概ねOKなのだけど,
□□□□□
□■■□□
□□■■□
□□□□□
の回転がうまくいかない.

nanagyounanagyou 2007/11/04 13:09 ども、7行テトリス作者のnanagyouです。痛いニュースに掲載されていたとはw
2chなどの掲載版は7行到達時のものであり、その後それなりに縮めてありますので、ぜひご覧ください。
http://www.geocities.jp/nanagyou/list.html

OzyOzy 2007/11/04 16:45 おお!nanagyouさんの作品だったのですねー!!
変態コードなわけだ(笑)そうか,(p/9|0)でうまく回転できるんですね.
ここまできたら6行でなんとかなりませんかね^^;

1234612346 2009/09/15 21:20 今見てる人居るのかな・・・?
6行に収めました!アルゴリズム全くいじってませんが^^;

<body onKeyDown=K=event.keyCode-38 onload="Z=X=[B=A=12];function Y(){for(C=[q=c
=i=4];f=i--*K;c-=!Z[h+(K+6?p+K:C[i]=p*A-(p/9|0)*145)])p=B[i];for(c?0:K+6?h+=K:t
?B=C:0;i=K=q--;f+=Z[A+p])k=X[p=h+B[q]]=1;h+=A;if(f|B)for(Z=X,X=[l=228],B=[[-7,-
20,6,h=17,-9,3,3][t=++t%7]-4,0,1,t-6?-A:2];l--;)for(l%A?l-=l%A*!Z[l]:(P+=k++,c=
l+=A);--c>A;)Z[c]=Z[c-A];for(S='';i<240;S+=X[i]|(X[i]=Z[i]|=++i%A<2|i>228)?i%A?
'■':'■
':'_');D.innerHTML=S+P;Z[5]||setTimeout(Y,i-P)}Y(h=K=t=P=0)" id=D>

1234612346 2009/09/15 21:24 あれ?<br>が改行されてる・・・。連投ごめんなさい。
うまくいかなくてもこれでやめますので。

<body onKeyDown=K=event.keyCode-38 onload="Z=X=[B=A=12];function Y(){for(C=[q=c
=i=4];f=i--*K;c-=!Z[h+(K+6?p+K:C[i]=p*A-(p/9|0)*145)])p=B[i];for(c?0:K+6?h+=K:t
?B=C:0;i=K=q--;f+=Z[A+p])k=X[p=h+B[q]]=1;h+=A;if(f|B)for(Z=X,X=[l=228],B=[[-7,-
20,6,h=17,-9,3,3][t=++t%7]-4,0,1,t-6?-A:2];l--;)for(l%A?l-=l%A*!Z[l]:(P+=k++,c=
l+=A);--c>A;)Z[c]=Z[c-A];for(S='';i<240;S+=X[i]|(X[i]=Z[i]|=++i%A<2|i>228)?i%A?
'■':'■<br>':'_');D.innerHTML=S+P;Z[5]||setTimeout(Y,i-P)}Y(h=K=t=P=0)" id=D>

OzyOzy 2010/03/25 16:47 どもども(´ー`)
「6行テトリス」というエントリで新たに書いておきました。