The net is vast
プログラミングや、コンピュータなどの備忘録です。 主にRuby, Java, Linux, 等を扱います。アルゴリズムも扱いたいな。
0:44

fastlookup_bookmarklet ブックマークレットで辞書を引く

Category: By jx

fastlookup alc なんかがあると、辞書を引くのが簡単です。でも、userscriptが使えないとだめだったりして、最近はもっぱらChromeを使用しているため、使えません。仕方ないので、YAHOO Pipesを利用して、YAHOOの英和辞書を引くブックマークレットを作成しました。自分はIEを使わないので、IEには非対応ですが、簡単に対応できるはずです。

必要なときだけブックマークレットを読みこめばいいし、使い勝手は悪くないと思います。

使い方は簡単。ブックマークレットを実行したら、辞書を引きたい単語を選択してください。Firefox, Webkit系で動くはずです。

fastlookup_bookmarklet

 
0:12

Dijkstra's AlgorithmとA-Star AlgorithmをJavaScriptで実装してみた

Category: , By jx

ダイクストラ法とA-StarアルゴリズムをJavaScriptで実装してみた。

ダイクストラ法は確かに動いているように思えるけど、A-Starの方はうまく動いていないように見えるというか、全然高速化されていない。こんなもんなのかな?知ってる人いたら教えてください。

Create Map:
(function() {
var start;
var tdList;
var mapSize = 10;
var map; 
var dijkstra = function(sx, sy, gx, gy, astar) {
 var startTime = new Date().getTime();
 var masterList = new NodeList(); // Node全てを格納するリスト
 var openList = new NodeList(); // スコアが確定していないノードを格納するリスト
 var closeList = new NodeList(); // スコアが確定したノードを格納するリスト
 var maxWidth = map[0].length; // 地図の幅
 var maxHeight = map.length; // 地図の高さ

 message(''); // ログ
 // 地図データからノードを作成
 for (var i = 0, len = map.length; i < len; i++) {
  for (var j = 0, jlen = map[i].length; j < jlen; j++) {
   masterList.add(new Node(j, i));
  }
 }

 // スタートノードの設定
 var targetNode = masterList.get(sx, sy);
 targetNode.score = 0;
 closeList.add(targetNode); // スタートノードはcloseListに格納しておく

 var whileCount = 0;
 while (true) {
  whileCount++;
  // 次のノードを探索
  var checkNodePositions = [[targetNode.x, targetNode.y - 1], [targetNode.x, targetNode.y + 1], [targetNode.x - 1, targetNode.y], [targetNode.x + 1, targetNode.y]];
  for (var i = 0, len = checkNodePositions.length; i < len; i++) {
   var checkNodePosition = checkNodePositions[i];
   // 地図の範囲外であれば探索しない
   if (checkNodePosition[0] < 0 || checkNodePosition[0] > maxWidth - 1 ||
     checkNodePosition[1] < 0 || checkNodePosition[1] > maxHeight - 1) {
    continue;
   }
   var checkNode = masterList.get(checkNodePosition[0], checkNodePosition[1]);
   if (checkNode.type == 0) continue; // 壁だったら処理しない
   if (closeList.get(checkNodePosition[0], checkNodePosition[1])) continue; // スコアが確定していればなにもしない
   if (!openList.get(checkNodePosition[0], checkNodePosition[1])) {
    openList.add(checkNode); // openListにもcloseListにも無ければopenListに格納しておく
   }
   var score;
   if (astar) {
    score = targetNode.score + 1 + Math.abs(checkNodePosition[0] - gx) + Math.abs(checkNodePosition[1] - gy);
    //console.log(score);
   } else {
    score = targetNode.score + 1; // この経路を辿ったときのスコアはtargetNode.score + 1
    //console.log(score);
   }
   // スコアが格納されていない、またはほかの経路よりも効率が良ければスコアと、一つ前のノードをセットする
   if (isNaN(checkNode.score) || checkNode.score > score) {
    checkNode.score = score;
    checkNode.parent = targetNode;
   }
  }
  // openListが0になってしまったら、辿ることができないということ
  if (openList.length() == 0) {
   message('No route!');
   return;
  }
  // 現在openListに格納されている最小のスコアのノードはスコアを確定し、closeListに格納する
  targetNode = openList.getMin();
  openList.remove(targetNode);
  closeList.add(targetNode);
  targetNode.score = targetNode.score;
  if (targetNode.x == gx && targetNode.y == gy) break;
 }
 var endTime = new Date().getTime();
 message(endTime - startTime + 'ms' + ' whileCount:' + whileCount);
 showRoute(targetNode); // ルートを表示する
}
var message = function(value) {
 document.getElementById('message').innerHTML = value;
}
var showRoute = function(targetNode) {
 var td = tdList.get(targetNode.x, targetNode.y);
 td.className = 'scotch route';
 td.style.backgroundColor = 'green';
 var parent = targetNode.parent;
 if (parent) showRoute(parent);
}
var createMapData = function(count) {
 map = [];
 start = [0, 0];
 for (var i = 0, len = mapSize * count; i < len; i++) {
  var row = [];
  for (var j = 0, jlen = mapSize * count; j < jlen; j++) {
   var r = Math.floor(Math.random() * 100) % 5;
   row.push(r);
  }
  map.push(row);
 }
}
var createMap = function() {
 var graph = document.getElementById('graph');
 graph.innerHTML = '';
 var table = graph.appendChild(document.createElement('table'));
 table.style.borderCollapse = 'collapse';
 var tbody = table.appendChild(document.createElement('tbody'));
 tdList = new Table();

 for (var i = 0, len = map.length; i < len; i++) {
  var tr = tbody.appendChild(document.createElement('tr'));
  var row = [];
  for (var j = 0, jlen = map[i].length; j < jlen; j++) {
   var td = tr.appendChild(document.createElement('td'));
   observe(td, 'click', analyse);
   td.style.border = '1px solid white';
   td.style.width = '10px';
   td.style.height = '10px';
   if (map[i][j] == 0) {
    td.className = 'scotch wall';
    td.style.backgroundColor = 'red';
   }
   else td.className = 'scotch';
   tdList.set(j, i, td);
  }
 }
}
var analyse = function(event) {
 var target = event.target || event.srcElement;
 var trChildren = target.parentNode.children;
 var tbodyChildren = target.parentNode.parentNode.children;
 var x,y;
 for (var i = 0, len = trChildren.length; i < len; i++) {
  if (trChildren[i] == target) {
   x = i;
   break;
  }
 }
 var tr = target.parentNode;
 for (var i = 0, len = tbodyChildren.length; i < len; i++) {
  if (tbodyChildren[i] == tr) {
   y = i;
   break;
  }
 }
 if (start[0] == x && start[1] == y) {
  message('Start is equals to Goal');
  return;
 }
 if (target.className.indexOf('wall') != -1) {
  message('Your clicked cell is wall');
  return;
 }
 // routeをクリアする
 tdList.each(function(td) {
  var className = td.className;
  var classNameList = className.split(/ /);
  for (var i = classNameList.length - 1; i >= 0; i--) {
   if (classNameList[i] == 'route') {
    classNameList.splice(i, 1);
    td.style.backgroundColor = '';
   }
  }
  td.className = classNameList.join(' ');
 });
 var astar = document.getElementById('astar20090824').checked;
 dijkstra(start[0], start[1], x, y, astar);
 start = [x, y];
}
var observe = function(target, type, listener) {
 if (target.addEventListener) target.addEventListener(type, listener, false);
 else target.attachEvent('on' + type, function() { listener.call(target, window.event); });
}
var Node = function(x, y) {
 this.x = x;
 this.y = y;
 this.type = map[y][x];
}
Node.prototype.score = NaN;
Node.prototype.parent = null;

var NodeList = function() {
 this.data = {};
}
NodeList.prototype.add = function(value) { this.data[value.x + ',' + value.y] = value; }
NodeList.prototype.get = function(x, y) { return this.data[x + ',' + y]; }
NodeList.prototype.length = function() {
 var count = 0;
 for (var key in this.data) {
  count++;
 }
 return count;
}
NodeList.prototype.remove = function(value) { delete this.data[value.x + ',' + value.y]; }
NodeList.prototype.getMin = function() {
 var data = this.data;
 var min = null;
 for (var node in data) {
  if (!min) {
   min = data[node];
   continue;
  }
  if (min.score > node.score) min = data[node];
 }
 return min;
}
var Table = function() {
 this.data = {};
}
Table.prototype.set = function(x, y, value) { this.data[x + ',' + y] = value; }
Table.prototype.get = function(x, y) { return this.data[x + ',' + y]; }
Table.prototype.each = function(func) {
 var data = this.data;
 for (var key in data) {
  func(data[key]);
 }
}

observe(document.getElementById('mapSelect20090824'), 'change', function(event) {
 var target = event.target || event.srcElement;
 var value = target.value;
 createMapData(value);
 createMap();
});
createMapData(1);
createMap();
})();
 
14:00

XenServerのインストールPDFがすばらしい

Category: By jx
XenServerが無償化されているので、全てのサーバリソースをXenServerにしてみようかとインストールしてみた。XenServerのインストールに関してエントリーを書こうと思ったら本家の日本語サイトにCitrix XenServer 5.0 無償版インストール Step by Step Guide(PDF)が置いてあった。 これを見てみると、XenServerを動かすまでの全ての手順が載っているので、大変わかりやすい。まぁXenServerは動かすのが簡単なので、ドキュメントもいらないくらい。インストールには30分もかからないほど簡単。 XenServerでOSを動かせば、マシンを買い替えてハードウェアが変わっても、マシンイメージを異動すればそれで環境移行が完了してしまうので楽。さらに、ライブマイグレーションを使えば、Xen上で動いているマシンをほかの物理マシンに動作しているまま移行させることができる。これはすばらしすぎる。 自宅サーバで運用していると人は是非XenServerを考えてみてはいかがだろう。
 
23:08

gem 1.1から1.3へのアップデートではまる

Category: By jx
ずいぶん前にRailsをやってから、しばらく触ってなかったので、gemが1.1のままでした。NetBeansでRailsプロジェクトを作るとGemが1.3.1以上じゃないとダメだよとおこられてしまったので、Gemをアップデートしようとすると、
$ sudo gem update --system Updating RubyGems Bulk updating Gem source index for: http://gems.rubyforge.org/ Nothing to update
といわれて、アップデート出来ない。 どうしたら良いのかなと思って調べていたらgem update --system で失敗する場合にはという記事を発見。以下のコマンドでアップデート完了です。
$ sudo gem install rubygems-update $ sudo update_rubygems
 
23:37

紙の本が100%亡くなることは無い

Category: By jx
紙の本が100%亡くなると断言できる、たった一つの理由
断言できる理由、それは紙の本が"印刷"という技術だからです。そして、「紙の本に限ってそれは無い」と錯覚しやすいのは、「紙に印刷する」という技術があまりの大発明であったからです。あまりに長く親しまれすぎて、それが技術だと認識できないのです。 技術と言うのは、必ずそれを上回るまったく新しい技術によって取って代わられる運命にあります。
何死ぬほど眠たい事言ってるんでしょうか。一般層への普及の条件というものをはき違えています。印刷という技術が普及したんじゃないんですよ、印刷したものが便利だったから普及したんです。技術だから新しいものにとって代わられるんじゃない。使いやすいからみんながそっちを使うんです。 既存の技術が新しい技術に取って代わられるというのは、「同じこと」を実現するのに、より性能の良いもの、コストの安いものの時に成り立つことです。今回の比較はインタフェースが異なってしまいます。使い勝手違います。もし、kindleのような電子ブックリーダーを想定してそのようなことを言っているとしたら、お門違いも甚だしいです。
"音"を記録する音楽メディアは、この100年ほどの間にレコード→カセット→CDと変遷してきました。そして今はCD→ダウンロード、となる過渡期です。
この例では音楽を挙げていますが、この媒体の目的は音楽を聴くことが目的で、レコード、カセット、CD、ダウンロード、どれもイヤホン(スピーカー)を通して聴きます。インタフェースが変わっていないのです。インタフェースが変わらないのであれば、より小型、よりポータブルなものがより利便性が高いことは間違い在りません。だから、音楽という媒体は、この変遷を辿ったのです。 紙の本は状況がことなります。電子ブックリーダーという媒体を考えるのであれば、やはりインタフェースとして非力です。書き込めないし、次のページへの移動が、ページ遷移となってしまって連続しなくなってしまいますし、どれだけめくったのが実感できなかったり。 紙という媒体以上に便利なものを想像できますか?そもそも、人間が想像出来ないものは作ることはできません。もちろん、これから検索出来るという利便性から電子媒体のものは増えていくでしょう。しかし、やはりそれは一部の機械好きの人たちのガジェットに過ぎず、紙という媒体の代わりにはなりえません。 技術は生活をより便利にするものです。より便利になるものであれば古いものに取って代わりますし、そうでなければ変わることはできないでしょう。そして、人間は想像すらできないものは作ることができません。
 
1:37

GAE/JでXMLを操る

Category: By jx
GAE/Jで開発をしていると、どうしてもXMLを操らなきゃいけないときがあります。開発機でRomeを使って動いたぞと思って本番環境にデプロイしても動作しません。下のような例外が発生してしまいます。
Could not load default SAX parser
なんて言われてしまいます。これを解決するにはxercesの次のjarが必要になります。
  • serializer.jar
  • xercesImpl.ja
  • xercesSamples.jar
  • xml-apis.jar
これでも実はまだ足りません。XPathを使おうと思っても、xercesにはXPathのAPIは用意されておらず、
XPathFactory.newInstance()
上のようにするとやはり例外が発生してしまいます。
XPathFactoryConfigurationException: javax.xml.xpath.XPathFactoryConfigurationException: No XPathFactory implementation found for the object model: http://java.sun.com/jaxp/xpath/dom
これを解決するには、xalanが必要になります。 結局、xalanにはxercesが含まれている?ので結局、xalan-j_2_7_1の以下のjarをWEB-INF/libの下に配置します。
  • serializer.jar
  • xalan.jar
  • xercesImpl.jar
  • xml-apis.jar
  • xsltc.jar
さらに、
XPathFactory.newInstance()
のように書いてもダメで、次のように書かなければ行けません。
new org.apache.xpath.jaxp.XPathFactoryImpl();
まとめると、
  1. Romeを使用して
  2. xalanのjarを使って
  3. new org.apache.xpath.jaxp.XPathFactoryImpl()で、Factoryを作成します
 
19:00

「はまらない」ような体制を作ろう

Category: By jx
小野和俊のブログ:プログラマーの開発速度は「はまる」時間の長さで決まる 「はまる」時間で開発速度が決まるのであれば、そもそも「はまらない」ようにすればいい。そういう体制を作ろう。 周りがいつもハマっていたりする原因は、その使用するフレームワークや技術を誰も知らないとき。だったら、そんなもの使わずに、わかっているものを使えば良い。特に最近の重厚なフレームワークなんかを使った場合には、つぎはぎでつないできたプロジェクトが、最後の方でにっちもさっちもいかなくなってしまうようなことが多い。 上のように考えても、新しい技術やフレームワークを使うメリットが在ると感じるならば、わかっている人をつれてこよう。開発することが決まってから、自分たちだけで新しい技術を見極めるなんて並たいていの人ができることじゃない。 コーダーとしては、小野和俊さんの言う通りのことを気をつければ良いと思う。ただ、 そのパフォーマンスを決めてしまうのは、プロジェクトの方針を決めてしまう人だから、重要なフェーズでは気をつけて判断してほしい。