投稿記事

ウラムの螺旋

21 May 2015


3736 3534 333231
3817 1615 141330
3918 54 312 29
4019 61 21128
4120 78 910 27
4221 2223 2425 26
4344 4546 47

中央の1から反時計回りに数字を置いてゆき、素数が現れたところに印をつけていくという作業をして、描いたのが「ウラムの螺旋」です。1963年、数学者のスタニスワフ・ウラムによって発見され、彼によれば学会の「長くて非常に退屈な論文」の発表の際に落書きをしていてこれを発見した。

run ボタンをクリックしてください。 自然数50,000以下で出現する素数を表示しています。


var startNumber = 1;
var maxNumber   = 50000;
var m = 0; // move のカウンター
var step = 1;
var p = 1;

// 移動方向の定義
var move = [
  {"x":2,"y":0},{"x":0,"y":2},{"x":-2,"y":0},{"x":0,"y":-2}
];

var x0,y0; //初期座標x,y

/** 
    エラストテネスの篩    */

// 配列作成
var searchList = []; //探索リスト
var workList = [];   //作業用リスト
var primeList = []; //素数リスト
//最初の探索リストを作成(2から)
for (var i = 2; i <= maxNumber;i++){
  searchList.push(i);
};


// 篩にかけます
while(searchList[0]<= Math.sqrt(maxNumber)){
  for (var i = 0; i < searchList.length; i++) {
    if (i==0) {primeList.push(searchList[i])};
    if ((searchList[i] % searchList[0]) != 0) {
      workList.push(searchList[i])
    };
  };

  searchList = workList;
  workList = [];

};

//探索リストに残った数を、素数リストに追加する。
for (var i = 0; i < searchList.length; i++) {
  primeList.push(searchList[i]);
};

searchList = [];

var svg01 = d3.select("#svg01")
              .append("svg")
              .attr("height",500)
              .attr("width",500)
              .style("background","#222");
var xScale01 = d3.scale.linear()
                     .domain([-250,250])
                     .range([0,500]);
var yScale01 = d3.scale.linear()
                     .domain([250,-250])
                     .range([0,500]); 


$("#run01").on("click", function(){

  svg01.selectAll("circle").remove();
  x0 = 0; //初期座標x
  y0 = 0; //初期座標y
  m = 0; // move のカウンター
  step = 1;
  p = 1;

  var i = 0;
  for (var n=startNumber+1;n<= maxNumber; n++) {

    x0 = x0 + move[m].x;
    y0 = y0 + move[m].y;

    if ((n==primeList[i]) && (n <= primeList[primeList.length-1])) {
      svg01.append("circle")
       .attr("cx", function(){ return xScale01(x0);})
       .attr("cy", function(){ return yScale01(y0);})
       .attr("r",1)
       .style("fill", function(){
        return "lime";
       });
 
       i++;
    };
   
    //移動する方向の変更     
    if (n==(p + step)) { //次の曲がり角に来たら
      m++;
      if (m>3) {
         m = 0;
      };
    };
    if (n==(p + 2*step)) { //2つ先の曲がり角に来たら
      m++;
      if (m>3) {
         m = 0;
      };
      p = p + 2*step; //新しい曲がり角を保持
      step++;         //繰り返し数を増やす
    }
  };

});