ActionScript3 で素数列挙を short coding

ActionScript3 で素数列挙の short coding にチャレンジしてみる。ネタ元はこれ。

元々のコードは JavaScript で「エラトステネスのふるい」を短く書いたもの。JavaScript のコードがあるんだから、ActionScript でも同じぐらいで書けるはずと信じてやってみた。

strict 版

まずは、warning が出ないもの。227文字。

package{import flash.display.*;public class C extends Sprite{public function C(){graphics.beginFill(0);for(var a:Array=[],c:int=1,d:int;c++<1E3;)if(!a[c]){for(d=c;d<1E3;)a[d+=c]=1;graphics.drawRect((c%10)*5,int(c/10)*5,5,5)}}}}

出力はこんな感じ。

10個ごとに素数の数字を黒い点で表している。左上が 0 で、右にいくと 2, 3 が連続して素数として現れて、そのあと、5,7 と続く。2段目からは 11, 13, 17, 19 が現れる。

少し考えたら当たり前だと分かるのだけど下一桁が 0,4,6,9の列は素数が1つも現れないし、2,5の列は一番上にしか素数が登場しない。10以上の素数の下一桁は 1,3,7,9 のいずれかなのだ。こうやって図にしてみると、改めて気づかされて面白い。

で、肝心のソースコードのインデントを復元するとこんな感じ。

package{
import flash.display.*;
public class C extends Sprite{
    public function C(){
        graphics.beginFill(0);

        // 1から1E3(=1000)までループを回す
        for(var a:Array=[],c:int=1,d:int;c++<1E3;)
            // 素数かどうか判定
            if(!a[c]){
                // 素数のとき:
                // c*2,c*3,c*4... で a のフラグを立てる
                for(d=c;d<1E3;)
                    a[d+=c]=1;

                // 該当する位置に四角を描画する
                graphics.drawRect((c%10)*5,int(c/10)*5,5,5)
            }
    }
}
}

短くするための工夫は色々してある。思いつく範囲で列挙するだけでも

  • コンストラクタでは戻り値 :void を書かなくても warning は出ない
  • graphics.endFill() がなくても動くのでやらない
  • Math.floor() は int() で代用
  • 変数宣言は1箇所にまとめる。しかも for の中でやっちゃうことで、var 文の ; を節約できる
  • ; を省略できるところは省略しちゃう

といったあたり。

これより短くできるのか気になる。ルールは

  • ライブラリは使用せず、Flash がネイティブに提供する API を利用すること
  • 素数の表示方法は問わない

といったあたりか。ただ、TextField 使ったら import flash.text.*; だけでかなりの文字数になるし、BitmapData は初期化と表示に文字数食われるし、Graphicsを使うのが最短な気がしている。

strict じゃない版

warning が出てもいいならもう少し短くできる。210文字。

package{import flash.display.*;public class C extends Sprite{public function C(){for(var g=graphics,a=[],c=1,d;c++<1E3;)if(!a[c]){for(d=c;d<1E3;)a[d+=c]=1;g.beginFill(0);g.drawRect((c%10)*5,int(c/10)*5,5,5)}}}}

いちおう、整形したソースコードを掲載しておく。

package{
import flash.display.*;
public class C extends Sprite{
    public function C(){
        for(var g=graphics,a=[],c=1,d;c++<1E3;)
            if(!a[c]){
                for(d=c;d<1E3;)
                    a[d+=c]=1;
                g.beginFill(0);
                g.drawRect((c%10)*5,int(c/10)*5,5,5)
            }
    }
}
}

型宣言しなくてもいい分だけ短くなった。

また、今までは graphics と2回入力していたが、g=graphics, の11文字を追加することで、graphics(8文字) が g の1文字で済むようになった。graphics は2回登場していたので、16文字が13文字に減ったので3文字の節約だ。ただ、そのせいで beginFill() する位置が変化したが、これでも動いてるので問題はないこととする。


まとめ

これ以上短くできるのかな。挑戦者求む。ソースは wonderfl に投稿してある。

Short Coding ~職人達の技法~

Short Coding ~職人達の技法~

  • 作者: Ozy
  • 出版社/メーカー: 毎日コミュニケーションズ
  • 発売日: 2007-08-09
  • メディア: 単行本(ソフトカバー)
  • Amazon のレビューを見る