エラトステネスの篩
パッケージJava製品開発担当の大です。こんにちは。
震災から11日が経ちました。被害に合われた方々は、現在も大変なご苦労をされていることと思います。
謹んでお見舞い申し上げます。
さて、前回、前々回と素数にまつわる話を書きました。
その際Wikipediaをウロウロしてたらエラトステネスの篩のページにあたったのですが、
アルゴリズムを可視化しているアニメーションGIFが貼ってあって、わかりやすくていいなぁと思ったので、自分でも書いてみたくなりました。で、お手軽にJavaScriptで書いてみました。
可視化の前に
エラトステネスの篩(ふるい)についてものすごくさらっと説明しておくと、ある整数以下の全ての素数を発見するためのアルゴリズムです。
詳しいことはWikipediaのページを見てください。
JavaScriptで可視化
実行ボタンを押してみてください。可視化します。
2~2000までの値を指定して実行できます。
までの素数を検索します。
見つかった素数:
ソース
こんな感じです。久しぶりにJavaScriptを書いてみましたが、やっぱりクロージャのある言語は楽しいですね!
jQueryは全然使いこなせてないですが。。。
function Eratosthenes($) { var UNKNOWN = -1; var DEFAULT_LENGTH = 100; var MIN_LENGTH = 2; var MAX_LENGTH = 2000; var self = this; var list; var queue; // 数列を篩にかけます。 // 素数か合成数かが判別できた時点でqueueに入れてます。 this.sieve = function() { for (var i = 2; i < list.length; i++) { if (list[i] != UNKNOWN) { continue; } var color = newColor(); list[i] = i; queue[queue.length] = {n: i, color: color}; if (i * i > list.length) { continue; } for (var j = i * 2; j < list.length; j += i) { if (list[j] != UNKNOWN) { continue; } list[j] = i; queue[queue.length] = {n: j, color: color}; } } this.visualize(0); } // queueの順に判別した様を可視化します。 this.visualize = function(index) { if (index < queue.length) { var n = queue[index].n; if (n == list[n]) { $('#primes').append(' ' + n); $('#td' + n).css('border-color', '#ff0000'); } $('#td' + n).css('background-color', queue[index].color); setTimeout(function () {self.visualize(index + 1);}, Math.floor(10000/list.length)); } } // 色を適当に作成します。 // 薄めの色で隣り合う色がなるべく判別しやすいように。。。 var newColor = (function() { var times = 0; return function() { var color = '#'; for (var i = 0; i < 3; i++) { var c = times % 3 == i ? 0xFF : (Math.floor(Math.random() * 0x7F) + 0x7F); color += c.toString(16); } times++; return color; }; })(); // 初期化します。 var init = function() { var len = parseInt($('#length').val()); if (isNaN(len)) { len = DEFAULT_LENGTH; } else { len = Math.max(len, MIN_LENGTH); len = Math.min(len, MAX_LENGTH); } $('#length').val(len); list = new Array(len + 1); list[0] = 0; list[1] = 1; for (var i = 2; i < list.length; i++) { list[i] = UNKNOWN; } $('#nlist').empty(); var tr; for (var i = 1; i < list.length; i++) { if (i % 10 == 1) { tr = $('<tr>'); $('#nlist').append(tr); } tr.append($('<td>').attr('id', 'td' + i).text(i)); } $('#primes').empty(); queue = new Array(); } init(); }