« 2006年08月 | メイン | 2006年10月 »

2006年09月30日

続:Pythonドキュメントの日英マッピングをするGreaseMonkey

西尾泰和のブログ: Pythonドキュメントの日英マッピングをするGreaseMonkeyの改良版。IDの付いているエレメント(関数の定義とか)全ての前にリンクが付いて、それをクリックすると対応する日本語ドキュメントの同じエレメントへジャンプ。 pyenjamapper2.user.js

// ==UserScript==
// @name          Python English-Japanese Mapper 2
// @namespace     http://www.nishiohirokazu.org/blog/2006/09/pyenjamapper2.html
// @description	  mapping English documents and Japanese documents
// @include       http://www.python.org/doc/2.4/*
// @include       http://www.python.jp/doc/release/*
// ==/UserScript==


// mapping
// [from, to, label]
mapping = [
  [
    "http://www.python.org/doc/2.4/",
    "http://www.python.jp/doc/release/", "[J]"
  ],
  [
    "http://www.python.jp/doc/release/",
    "http://www.python.org/doc/2.4/", "[E]"
  ],
]

loc = document.location.toString();

caption = "";
for(var i = 0; i < mapping.length; i++){
  var frm = mapping[i][0];
  if(loc.indexOf(frm) == 0){
    var url = loc.replace(frm, mapping[i][1]).split("#")[0];
    caption = mapping[i][2];
    break;
  }
}

tags = document.getElementsByTagName('*');
for(var i = 0; i < tags.length; i++){
  tag = tags[i];
	if(tag.id != ''){
		newTag = document.createElement('A');
		newTag.href = url + '#' + tag.id;
		newTag.appendChild(document.createTextNode(caption));
		tag.parentNode.insertBefore(newTag, tag);
		i++;
	}
}

対応づけられたサイトの切り替えをするブックマークレット

Pythonドキュメントの日英マッピングをするGreaseMonkeyの続編。enjamapper。 これをブックマークしておいて、 http://www.python.org/doc/2.4/* か http://www.python.jp/doc/release/* のどちらかで実行すると、もう片方のサイトにジャンプします。

実行されると即ジャンプするブックマークレットにすることで、HTMLを書き換えないでよくなるので、ターゲットのHTMLに対する依存性がなくなりました。サイトの対応付けの設定を書き換えるだけで、ファイルの配置が同じサイト間ならPythonのドキュメントに限らずジャンプできます。

サイトの対応付けをカスタマイズしたい場合や、僕のサイトに誰かが進入してスクリプトを有害な物に差し替えてしまう危険性を避けたい場合は enjamapper.js をダウンロードして自分の好きなところにおいてください。

使い方の具体例。 例えばPythonドキュメントの和訳中に 「positional arguments」はどう訳すのだろうと思ったとします。まず、Googleのsite:オプションを利用して「positional arguments site:http://www.python.org/doc/2.4/」と検索します。そうすると英文Pythonドキュメント中の「6.21.1.3 What are positional arguments for?」という項目がヒットします。これを開いて、enjamapperブックマークを実行すると、これに対応する日本語のページ「6.21.1.3 固定引数とは何か」にジャンプします。「positional arguments」は「固定引数」と訳せば他のドキュメントと統一できるということがわかりました。

ソースコードは以下。

// English-Japanese Mapper Bookmarklet
// see http://www.nishiohirokazu.org/blog/2006/09/enjamapper.html


mapping = [
  [
    "http://www.python.org/doc/2.4/",
    "http://www.python.jp/doc/release/"
  ]
]

loc = document.location.toString();
for(var i = 0; i < mapping.length; i++){
  var url1 = mapping[i][0];
  var url2 = mapping[i][1];
  if(loc.indexOf(url1) == 0){
    document.location = loc.replace(url1, url2);
  }else if(loc.indexOf(url2) == 0){
    document.location = loc.replace(url2, url1);
  }
}

Pythonドキュメントの日英マッピングをするGreaseMonkey

追記:これを改良して作った対応づけられたサイトの切り替えをするブックマークレットの方が便利かも知れません。


pyenjamapper。Firefoxを使っていて、GreaseMonkeyをインストールしていれば、このリンクをクリックするだけでインストールしてください。そうすると 2.2 Non-essential Built-in Functionsなどの英文ドキュメントのナビゲータの所に「Japanese」というリンクが表示されます。クリックすると日本語の2.2 非必須組み込み関数 (Non-essential Built-in Functions)へ飛びます。こちらにはEnglishというリンクが追加されていて、クリックすると英語の方のドキュメントに飛びます。

他のブラウザの人でもブックマークレットとして使えるかも。…でも、ブックマークレットにするなら「押したらリンク追加」より「押したらジャンプ」の方がいいですね。

以下ソースコード。

// ==UserScript==
// @name          English-Japanese Mapper
// @namespace     http://www.nishiohirokazu.org/blog/2006/09/pyenjamapper.html
// @description	  mapping English documents and Japanese documents
// @include       http://www.python.org/doc/2.4/*
// @include       http://www.python.jp/doc/release/*
// ==/UserScript==


// mapping
// [from, to, label]
mapping = [
  [
    "http://www.python.org/doc/2.4/",
    "http://www.python.jp/doc/release/", "Japanese"
  ],
  [
    "http://www.python.jp/doc/release/",
    "http://www.python.org/doc/2.4/", "English"
  ],
]

loc = document.location.toString();
anchorTag = "";
for(var i = 0; i < mapping.length; i++){
  var frm = mapping[i][0];
  if(loc.indexOf(frm) == 0){
    var url = loc.replace(frm, mapping[i][1]);
    anchorTag = "<a href = '" + url + "'>" + mapping[i][2] + "</a>";
    break;
  }
}

naviDiv = '<div class="online-navigation">';
document.body.innerHTML = document.body.innerHTML.replace(
  naviDiv, naviDiv + anchorTag
);

Python Developers Camp日記

listを継承したクラスを作ると何が変わるか。

>>> class MyList(list):
	pass

>>> dir(MyList())
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__dict__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__module__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__str__', '__weakref__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>> [x for x in _ if not(x in dir(list))]
['__dict__', '__module__', '__weakref__']

この3つが増えている。

>>> set(dir(MyList())) - set(dir(list()))
set(['__dict__', '__module__', '__weakref__'])

これでいいらしい。なるほど。


__ タプルの本質は括弧ではなく、カンマなのだけど、わかりにくいのでつまずきやすい。タプルの本質を括弧だととらえていると、(1, 2, 3)、 (1, 2)ときたら(1)と書きたくなってしまう。でもこれは1を括弧で囲ってあるだけ。 タプルの本質はカンマで、単に人間が見やすくするためだけに括弧が付いている。「not "a" in "abc"」でいいのに「not("a" in "abc")」と書いたりするのと同じ。要素が3つのタプルは「1, 2, 3」だけでなく「1, 2, 3,」でもOK。2個のは「1, 2」と「1, 2,」が可能だが、要素が1個のは「1」と書くとダメなので「1,」だけになる。


__ 「foo.setAge(20)」とやるべき所を「foo.setAge = 20」と間違えることが出来てしまうのがJavaの人にとっては罠。


__ 演算子オーバーロードなのか、オーバーライドなのか、という話題。 多重定義 - Wikipedia。Pythonでは「x + y」が「x.__add__(y)」というフックメソッドの呼び出しで多重定義されている。xが整数オブジェクトなのか文字列オブジェクトなのかによって異なるメソッドだから、多重定義。これが演算子オーバーロード。で、整数クラスを継承した自作のクラスでその__add__メソッドをオーバーライドすると、足し算の挙動が変わる。これは単に「親クラスのメソッドをオーバーライドすると挙動が変わる」ってだけ。 同時に似た名前のことをやっているので紛らわしい。


__ 出先ではJavaScriptのリファレンスがなくて不便。 Pythonのドキュメントは個々の関数の説明の前にアンカーが付いてたりしないかと期待したけど残念ながらそうではない。代わりに<tt id='l2h-8' xml:id='l2h-8' class="function">なんてのが付いていたりする。

西尾泰和のブログ: Pythonドキュメントの日英マッピングをするGreaseMonkeyできました。「リンク先のページのxml:id='l2h-8'があるところへジャンプ」ってのがJavaScriptで出来るといいんだけど、どうすればいいんだろう。


__ 西尾泰和のブログ: 対応づけられたサイトの切り替えをするブックマークレット に進化しました。 あー、でも実際のユースケースを考えると、Googleの検索画面から直接使える方が便利かもなぁ。


__ なんだかすごく遠回りをしてしまったけど、アンカータグじゃないタグでもid="xxx"ならurlに#xxxってつけるだけでその位置に飛べるようですね。少なくともIEとFirefoxでは。それなら、もっとうまい方法があるかも…。


__ オーバーライドすべきメソッドであることを示すためにassert 0, "some message"と書く手もあるようだ。raiseでもいいのだけど。


__ 「Googleで訳語のわからない英語を検索して対応する和文に飛んで訳語を確認」というのをやろうと思ってせっかくURLのマッピングをするjsを作ったのに、バージョン2.4の英文ドキュメントに対してGoogleで検索しても、なんか引っかかってこない。functionが3カ所しか使われていないとかあり得ない。何が起きているのだろう。

仕方ないなぁ。英文は全部まとめたzipが落ちていたのでローカルに置いてあるから、Googleデスクトップを入れてそこから検索するというのも一つの手だけどなぁ。ううむ。自前で検索するプログラムを作るというのも一つの手だけどなぁ。というかインデクスを作らない片っ端からファイルを開いて読んで検索する物ならすでに作ってあるのだけど、Pythonの標準出力にファイル名が出てもなぁ。リンクが出て要約もでてクリックすればジャンプできるGoogleっぽいのがいいんだけどな。


__ リモートを妹に変えると面白い単語。リモート監視システム。リモートとの同期/差分。リモートコントローラー。リモートメンテナンス。リモートアシスタント。リモートリポジトリ。リモートセンシング。インターネット を使ったリモート教育。【コラム】ツールエキスパート 第1回 リモート管理もユビキタス? - VNC(1) (MYCOMジャーナル)。リモートのグラフィカルデバッグ。Microsoft SQL Server 2000 がリモート攻撃者のDosマウントを容認する。


__ DjangoのWindowsへのインストールは小学生でもできるくらい簡単だった。ダウンロードしてダブルクリックするだけだし。開発用のサーバを立てるまでもチュートリアルを読んだら簡単。流し読んだけど対話的に色々試せるようですね。もう眠い。

エレメントのIDと、次のIDが振られたエレメントまでの文章がデータベースに入れてあり、クエリを指定するとデータベースからマッチする行を選択して、その英文サイトへのリンクと和文サイトへのリンクを表示すればいいのか。いや、IDと英文と和文をデータベースに入れて、サマリー部分で並べて表示すれば、場合によってはリンクをクリックして飛ぶ必要すらない。詳しく見たいときだけリンク先を見ればいいし。で、ビューとしては検索フォームと、検索結果の表示があればいいのかな。

2006年09月29日

Python Developer Camp日記

遅れてつきましたが、遅れる人が多かったので時間割自体がシフトしていました。

Twistedはネットワークプログラムを書くための物らしい。勝手にウェブアプリを作るフレームワークだと思ってました。

和訳プロジェクト

  • 標準ドキュメントのビルドシステムが結構いい感じに出来ている。ReSTとか。docutilsとか。
  • 和訳のメリット
    • 人と情報を引き寄せる
    • 試行錯誤のコードが減る→信頼性が増す
    • ScreenCast お得感
    • 正確な情報はソフトウェアの信頼性も高める
  • リーダースのCDのやつがいいらしい
  • リポジトリのあるドキュメントが訳しやすい
  • Wikiの物も多いけど、Wikiのは翻訳しにくい
    • Wikiをリポジトリで管理したらいいのか?
  • 私見は入れない
  • 1ビットも情報を落とさない
  • 完成していない物より、下手でも完結している物を。投げ出さないこと。


__ 翻訳スプリント。難しい。投げ出したくなってきた。

日記

ソニー製バッテリーまたリコール:レノボ・IBMの50万個以上で過熱の恐れ - Engadget Japanese

僕のはリコール対象じゃなかったけど、喜んでいいのかどうか…。


__ 京葉線は復活したみたい。


__ 新富士まで新幹線で行ってそこからタクシーで10分か。2時間ちょい。開始が16時だからあと1時間で出発。 それまでに床にこぼした豚丼の汁をなんとかしないと!(ぉ)


__ 結局当初の予定通り、17時過ぎてからこっちを出発して夕食終わったくらいに到着する雰囲気。


__ 楽天KCから電話があって、三井住友の楽天カードを楽天KCのカードに切り替えた時点で口座引き落としの効力が切れているので、口座に振り込めとのこと。Viewカードも同じことを言っていたなぁ。なんか最近そういう電話が色々かかってくるからややこしくなってきた。

2006年09月28日

どの文字をXORすれば目的の文字になるか?

とりあえず「Hello, world!」のどの文字をXORすれば目的の文字になるかを載せておきます。ここに書かれている以外の組み合わせでも目的の文字を作ることが出来る可能性は高く、その「別解」の方がコードが短くなる可能性も否定できません。そのあたりの研究はまだ手つかずです。

!: !
": !^l^o
#:  ^l^o
$: H^l
%:  ^r^w
&: e^,^o
': H^o
(:  ^d^l
):  ^e^l
*:  ^e^o
+:  ^d^o
,: ,
-: e^H
.: e^H^l^o
/: l^,^o
0: e^H^o^r
1: ,^o^r
2:  ^e^w
3:  ^d^w
4: ,^o^w
5: e^H^o^w
6:  ^d^r
7:  ^e^r
8:  ^o^w
9: !^o^w
:: H^r
;:  ^l^w
<: !^o^r
=:  ^o^r
>:  ^l^r
?: H^w
@: l^,
A: e^H^l
B: e^H^o
C: ,^o
D:  ^d
E:  ^e
F:  ^e^l^o
G:  ^d^l^o
H: H
I: e^,
J:  ^o^r^w
K: H^l^o
L:  ^l
M: !^l
N: !^o
O:  ^o
P: H^o^w
Q:  ^l^o^r
R:  ^r
S: !^r
T:  ^l^o^w
U: H^o^r
V: !^w
W:  ^w
X:  ^e^o^r
Y:  ^d^o^r
Z: e^H^w
[: ,^w
\:  ^d^o^w
]:  ^e^o^w
^: ,^r
_: e^H^r
`:  ^l^,
a: !^l^,
b: !^,^o
c:  ^,^o
d: d
e: e
f: e^l^o
g: d^l^o
h:  ^H
i: !^H
j: o^r^w
k:  ^H^l^o
l: l
m:  ^!^l
n:  ^!^o
o: o
p:  ^H^o^w
q: l^o^r
r: r
s:  ^!^r
t: l^o^w
u:  ^H^o^r
v:  ^!^w
w: w
x: e^o^r
y: d^o^r
z: !^,^w
{:  ^,^w
|: d^o^w
}: e^o^w
~:  ^,^r

日記

渡辺さんの日記より、Kemuri/JavaScript

大歓迎です。確かにJavaScriptで作った方が手軽に試せますね。

とりあえず、対応表だけアップしときます。 西尾泰和のブログ: どの文字をXORすれば目的の文字になるか?


__ 台所漂白剤という物を使ってみたら目から鱗。洗いにくい隙間の汚れはこうやって落とすのかー。なるほど。


__ ぐち。JyConsole、バージョン1.2をダウンロードしたらファイル名に1.1と入っていて、解凍するとフォルダの名前はJyConsole 2.0。えー。

JyConsoleはQPL。GRINEditと静的にリンクするとライセンス上の問題が起こってしまうかも知れないなぁ。


__ NTTの「サツマイモで屋上緑化」っていいなぁ。芝より1.5倍吸収効率がいいらしい。コストは2倍かかるらしいけど。サツマイモは地面を這うから、屋上全部に土を敷き詰めなくてもいいそうな。


__ おなかすいた。 厚揚げとピーマンがある。 厚揚げは熱湯をかけて油を抜くらしい。 厚揚げとピーマンのみそ炒め


__ Python/Python病 - OreSign :: 俺だよ俺。それがオレSignクオリティ。

Javaでjava.util.regexやjava.lang.reflectをバリバリつかうようになる(もうリーマンプログラマじゃ読めねー)

あー、僕はPython病だったんだなぁ(笑)


__ あー。もう28時だ。 今日の夕方くらいにPython Developer Campに行かないといけないんだけどまだ場所がどこなのかいまいちわかってないぞ、むー。ラボで地図を印刷してくるのも忘れたし…。まぁ、なんとかなるだろう。


__ ちょっ、京葉線まだ復旧してないの!新木場~東京が運転見合わせって…。むー。秋葉原経由で行けばいいのかな。

2006年09月27日

log

短いことだから、整理されていないことだから、と開発日誌じゃなくて日記の方に書いてしまうと、 あとで集めて整理するのが大変なので全部開発日誌に書くようにしよう。

GRINEditのアーキテクチャ図を書いていて気がついたのだけど、 今はグラフオブジェクトが頂点オブジェクト、辺オブジェクト、物理法則オブジェクトを持っているけど、これはおかしいよね。グラフオブジェクトは頂点オブジェクト、辺オブジェクトを持っていて、整形エンジンオブジェクトが物理法則オブジェクトを持つべき。

そうすると、もし将来的に整形エンジンオブジェクトが複数個になりうるのであれば、「物理法則オブジェクトのセット」自体も複数個になりうる。難しい問題だなぁ。レンダリングエンジンを複数個使って、切り替えられるようにするニーズがどれほどあるのか…。


__ Graphクラスが持っていたlayoutStepとそれに関するメソッドをSimpleLayout implements ILayoutに移動。このlayoutStepは、引数にgraphを受け取って、それを破壊的に整形する。また、今までメインループでgraph.layoutStepと呼んでいたところを、Mediatorを介してmed.getLayoutEngine().layoutStepと呼ぶようにした。これでMediator.setLayoutEngineでレイアウトエンジンを指定することでグラフはそのまま整形方法を差し替えることが出来るようになった。


__ メインクラスGRINEditからデフォルトのGUIに関する処理を全てGRINEditDefaultGUIに移動。 でGRINEditクラスはnew GRINEditDefaultGUI()するだけ。 後はこのインスタンシエイト部分を能動的プラグインの読み込みに置き換えればOK。

ふむ。今GUI側にくくりだしたコードの部分にドラッグドロップのリスナとか、メニューの処理化スクリプトの呼び出しとかが入っているんだなぁ。

こういう機能をプラグインにくくり出すことを考えると、これはこのデフォルトのGUIを使うことが前提のプラグイン。ふむ。

日記

劇的ビフォーアフター。布団引く前に写真を撮った方がよかったですね。


__ 平石クリニックのニンニク注射というものを知って、打ってもらおうかと思って調べたんですけど、ニンニクが入っているわけではないんですね、これ。残念。


__ 404 Blog Not Found:かわいいからゆるす(c)Dr.秩父山から引用の引用

「インターネットとヤフーはどう違うんですか」と言われたら、要するに彼女は上位概念と下位概念を混同しているのだから、 「あなたの今の質問は、くだものとリンゴはどう違うんですか、と言っているのと同じです」 とか。

どうして誰もつっこんでいないのかそれが不思議なのですけど、この答えは「ここはひどいインターネットですね」と同じ間違いをしているような気がします。リンゴは果物ですけど、ヤフーはインターネットじゃないでしょう。果物とリンゴじゃなくて、スーパーとリンゴなのでは。


__ 明日というか今日は柏に行って貸しているMac miniをいじる予定。

2006年09月26日

日記あえ

おなかすいた…。

西尾泰和のブログ: How to make oneliner in Python?に英語のコメントが付いた。I afraid python would bite me!ってのは「Pythonスゲー!」ってニュアンスに解釈していいのかな??

もう9時回ってるし、10時のミーティングに間に合おうと思ったらうかうかしてられないね。


__ プロジェクトAとBとCがあって、AとBの締め切りが29日。Aから締め切りのないA'が派生したので捨てても構わなくなり、Bに注力していたらBはもう完了して後は数回のミーティングをのぞくと2ヶ月ほど放置しても構わない。で。今日はCの打ち合わせに行ってきて、漠然と「Bが終わったらそのノウハウを生かしてCをするのかな」と思っていたのが、予想に反してCがBの前に入ってきた。29日までAの完遂を目指して頑張り、29日からPythonDevelopersCampで、それが済んだらCかな。メインCでBと車輪の両輪で。

と思ったけどもやっぱり毛色の違うAに頭のリソースが向いていかないのでCと、Bの準備を。


__ 今朝、あごの関節がばきっといってしまって、ちょっと痛いような気もする。


__ 【防災】スーパーデリオス携帯用浄水器! - 総合防犯店マックスガレージ - livedoor デパート 意外と安いね。


__ なんか、仕事がはかどらないと思ったらもう1時半か。朝8時に起きて活動してウォッカ飲んで帰ってきてこの時間だったら、疲れて働けなくても当たり前。さっきからなんかふくらはぎや土踏まずが痛いと思っていたのだけど、僕はお酒を飲むと筋肉痛になる体質なのでそれがもう出始めているのだろう。

伏田君に教えてもらったWordの変更履歴表示機能が便利。彼に渡したドキュメントが変更箇所にびっしり赤が入って帰ってきたときにはぎょっとしたけど、自分の変更と人の変更で色が変わるし、変更を受け入れたり拒否して元に戻したり出来るし、なかなかいい。Wordで書類を出さないと行けなくて、複数人で文章をいじる場合にはかなり使える機能だと思った。

高市早苗沖縄北方少子化大臣の担当する内容は寿限無みたいに早口で一気に言えると面白そうです。沖縄及び北方対策、科学技術政策、イノベーション、少子化・男女共同参画、食品安全。

2006年09月25日

How to make oneliner in Python?

One day I fought on a boxing ring using my Thinkpad. It is a festival for nerds who loves lightweight language. (See Boxing in the LLRing?) My session was "Janken2.0", to make program to connect a server and play "Paper-Scissors-Rock". This entry is a FAQ, notFrequently Asked Question to make Python oneliner.

Is it difficult to make oneliners in Python?

You should learn Python more. Python use an indentation as a block. But what is the indentation? It is white region after "new line". No "new line" means no block, that is the most of syntax is disabled.

Is it impossible to make oneliners in Python?

No. See this. This is the "Paper-Scissors-Rock" agent.

jankenoneliner.png

How can I write "if" statement in a line?

"if" statement requires new line.

if condition:[new line]
    then-clause[new line]

if condition: then-clause[new line]

So, you can't use "if". Use "and" and "or".

condition and then-clause or else-clause

The right operand of "and" and "or" is evaluated lazily. But notice, if "bool(then-clause)" is False it doesn't work as you expected. You can envelope is with list

(a and [p(1)] or [p(2)])[0]

Given not-empty list as x, bool(x) is True.

How can I make a function?

"def" statement to make functions also requires "new line". So you must use "lamnda".

But lambda function can include expressions, not statements. You can't use assignments in lambda functions.

Oops, I can't use assignments?!

Don't worry. Python's great introspection allow you to remove assignment statements. The builtin function "globals()" returns global namespace as a dictionary. So when you want to do "x = 1", you just do "globals().__setitem__('x', 1)". Very easy. Sometimes you may use "locals()" for a local namespace and "x.__dict__" for a member of object x, but good programmers don't need them, because they use global namespace only.

How can I use "for" statements?

Why don't you use the list comprehension? I thought "for" statements were obsoleted.

>>> for i in range(5):
	print i

	
0
1
2
3
4
>>> import sys;[sys.stdout.write(str(i) + "\n") for i in range(5)]
0
1
2
3
4
[None, None, None, None, None]

[None, None, None, None, None] is the value of this expression. It is as True. You may have to use "and 0" to make it as False.

Is "while" statement replaced with recursive call?

Partially, yes. But if it loops too many times, it causes "RuntimeError: maximum recursion depth exceeded".

The other solution is lazy evaluation and infinite list. Import "ifilter" and "count" from itertools. "count" is a infinite list. "ifilter" creates a filtered list lazily. So "ifilter(bool, x).next()" evaluates x[0], x[1], x[2], ..., and stop iteration if x[n] is True.

>>> i = 1
>>> while i < 100:
	i *= 2

	
>>> i
128
>>> from itertools import ifilter, count; i = 1; ifilter(bool, ((i >= 100) or gl
obals().__setitem__("i", i * 2) for x in count())).next()
True
>>> i
128

How to substitute "break" statement and "else" clause?

It is very difficult. It is NOT difficult to write in Python, BUT difficult to write in English! "if condition: break" means "When the value of expression become paticular value, stop iteration". It is similar to the end of "while" statement. That is, the expression in "ifilter" should be as True when either the loop ended and the loop breaked. "else-clause" distinguish those two tarmination, so the value of expression must be different value.

I'll make this code to calculate prime numbers to oneliner.

>>> primes = []
>>> for i in range(2, 100):
	for p in primes:
		if i % p == 0:
			break
	else:
		primes.append(i)

>>> primes
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

First, substitute the "for" statement by a "while" statement.

>>> primes = []
>>> for i in range(2, 100):
	j = 0
	while j < len(primes):
		if i % primes[j] == 0:
			break
		j += 1
	else:
		primes.append(i)

		
>>> primes
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

I make the expression when "i % primes[j] == 0" the value becomes "BREAKED". When the loop tarminated without breaked, the value of loop become "True". After loop tarminated, if the value is "True", do "else-clause".

>>> globals().__setitem__("primes", []) or [
  globals().__setitem__("j", 0) or
  ifilter(bool,
    (
      not(j < len(primes)) or
      (i % primes[j] == 0 and "BREAKED") or
      globals().__setitem__("j", j + 1)
      for c in count()
    )
  ).next() == True and primes.append(i)
  for i in range(2, 100)
] and None
>>> primes
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

And I removed newlines and redundant spaces.

>>> globals().__setitem__("primes",[])or[globals().__setitem__("j", 0)or ifilter
(bool,(not(j<len(primes))or(i%primes[j]==0 and"BREAKED")or globals().__setite
m__("j",j+1)for c in count())).next()==True and primes.append(i)for i in range(2
,100)]and primes
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

How can I define a class?

There is no need to define your own class.

First, find a nice not read-only class or import it. Make an instance of the class. And push all fields and methods you need into it! Push, push, push!

If you need multiple instance, envelope the pushing code with lambda and make "builder function".

Here I wrote a sample to define a class.

>>> class Counter:
	def __init__(self):
		self.count = 0
	def __call__(self):
		self.count += 1
		return self.count

	
>>> c = Counter()
>>> c()
1
>>> c()
2

Import HTMLParser from HTMLParser, and push and push and push.

>>> from HTMLParser import HTMLParser; self = HTMLParser(); self.count = 0; self
.__call__ = lambda :self.__dict__.__setitem__("count", self.__dict__["count"] + 
1) or self.count
>>> self()
1
>>> self()
2

If you envelope them with lambda and assign it in global namespace, you can emulate the class definition.

>>> globals().__setitem__("Counter", lambda :(lambda self: self.__dict__.__setit
em__("count", 0) or self.__dict__.__setitem__("__call__", lambda :self.__dict__.
__setitem__("count", self.__dict__["count"] + 1) or self.count) or self)(__impor
t__("HTMLParser").HTMLParser()))
>>> c = Counter()
>>> c()
1
>>> c()
2
>>> c2 = Counter()
>>> c2()
1
>>> c()
3

How to "try" without "try...except"?

To catch a exception without try-statement is almost impossible. But I had to catch "Software caused connection abort" in my oneliner. I found a solution, it is not perfect substitution of "try...except", but it works.

Run the dengerous code as subprocess. When the subprocess dead, read its error message from the pipe and parse it.

    if sys.argv[3] == "CATCH":

        ifilterfalse(bool,
            (
                re.search("Software caused connection abort",
                    os.popen3(
                        r"python %s %s %s GO" % (
                            sys.argv[0],
                            sys.argv[1],
                            sys.argv[2]
                        )
                    )[2].read()
                )
                for x in count()
            )
        ).next()


    elif sys.argv[3] == "TRY":
        # dengerous code

It is work like following code.

while True:
    try:
        #  dengerous code
    except ....: # catch "Software caused connection abort" and ignore it
        pass

If you need some values from subprocess, you can use "cPickle" library. "cPickle.dumps(...)" and "globals.update(cPickle.loads(...))".

How to make import statements to expression?

Is it nessesary? If it is really nessesary, use built-in function __import__. But if you use global namespace only, you can simply import on the head of your code.

How to make short oneliner?

Find repeated string and make shorter. For example, "globals().__setitem__" is very frequent. Do "globals().__setitem__("g",globals().__setitem__)" or "globals().__setitem__("g",lambda x,y,z=globals():z.__setitem__(x,y))". If you have "not read-only and not callable" object x, try "x.__dict__.__setitem__("__call__", x.__dict__.__setitem__)".

Or compress it.

# Brainf*ck interpreter in Python Onliner Compressed
exec(reduce(lambda x,y:x.replace(y[0],y[1:]),'O1)q|Pz"t",|Qz"c",|Rimport |SY:zp,
|T)%256X|UY:z"c",c+1qp",p|V)or ifilter(bool,(|W)for x in count())).next()|Xqc",c
+1)q|Y",lambda|Z(globals().get(p,0)|q)or z"|zglobals().__setitem__('.split('|'),
'Rsys;from itertools Rcount,ifilter;[Q0qp",0qjY k:lambda:Z==0)^(k==-1)and(Pc+kqd
",1Vz"d",d+{"]":-1,"[":1}.get(s[t],0)*k)or d==0 or Pt+kWand Qt+1)or 1X>U+O<U-O+S
Z+1T-SZ+255T.Y:sys.stdout.write(chrZ)X,Sord(raw_input(">")[0]T[",j(O]",j(-Os",fi
le(sys.argv[1]).read()Vc==len(s)or(globals()[s[c]]()and 0W]'))

afterword

Thank you for reading this awful code written in English. I appreciate your patch to debug my English. Please feel easy to contact me!

KEMURI

This entry is an introduction of new programming language. Here is Japanese version.

KEMURI (means 'smoke' in Japanese) is proposed by NISHIO Hirokazu and OBINATA Daichi in the 39th symposium for young researcher of information science (jouhou kagaku wakate-no-kai in Japanese).

This is a code to print "Just Another Python Hacker," in KEMURI. Notice it is not the shortest code to print that. "^^"^^ can be replaced by ^"^^.

`"^^"^^^^"^^'"^^"^^'"^^"^^'"^^"^^"'"^^"^^`"^^"^^^^"^^"^^"^^"^^"^^'"^^"^^"'"^^"^^
`"^^'^^'"^^"^^'"^^"^^'"^^"^^'"^^"^^"'"^^"^^`'"^^"^^^^'"^^^'"^^"^^'"^^"^^'"^^"^^`
"^^"^^^^^^'"^^"^^'"^^"^^'"^^"^^`"^^"^^"^^'"^^^'"^^"^^'"^^"^^'"^^"^^^`'"^^"^^'"^^
"^^'"^^"^^'"^^"^^'"^^"^^'"^^"^^`"^^"^^^^"^^"^^'"^^"^^'"^^"^^'"^^"^^`"^^"^^^^'"^^
^'"^^"^^'"^^"^^'"^^^`"^^"^^^^'"^^"^^'"^^"^^'"^^"^^'"^^"^^`'"^^''^^'"^^"^^^'"^^"^
^'"^^"^^'"^^"^^`"^^"^^^^"^^"^^"^^^'"^^^'"^^"^^`"^^"^^^^"^^"^^"^^"^^''"^^^^'"^^"'
`'"^^"^^'"^^"^^'"^^"^^^^'"^^"^^'"^^"^^"'`"^^"^^^^"^^"^^'"^^"^^'"^^"^^'"^^"^^'"^^
"^^`"^^"^^^^"^^"^^"^^"^^"^^'"^^"^^"'"^^"^^`"^^'^^'"^^"^^'"^^"^^'"^^"^^'"^^"^^"'"
^^"^^`'"^^''^^'"^^"^^^'"^^"^^'"^^"^^'"^^"^^`"^^"^^^^"^^"^^"^^^'"^^^'"^^"^^`"^^"^
^^^'"^^"^^'"^^"^^'"^^"^^'"^^"^^`"^^"^^^^'"^^^'"^^"^^'"^^"^^'"^^^`^^'"^^"^^'"^^"^
^'"^^"^^'"^^"^^'"^^"^^`"^^"^^^^"^^"^^'"^^"^^'"^^"^^'"^^"^^`"^^"^^^^"^^"^^"^^^'"^
^^'"^^"^^`"^^"^^^^"^^"^^'"^^"^^^'"^^"^^^`'"^^"^^'"^^"^^'"^^^'"^^^^'"^^''`"^^"^^^
^"^^"^^^^^'"^^"^^'"^^"^^"'^"^^|

KEMURI is a Stack machine. You can push byte values (from 0 to 255) into stack. Each letter in KEMURI code is a command. There are only 6 commands in KEMURI syntax. The ^ pops two value from the stack and calculates XOR and pushes the result. The " duplicate the top value of the stack, that is, it pops a value and pushes itself twice. The ' pops three values x, y, z and pushes x, z, y. In other word, it rotates the top three values of the stack from xyz to yzx. The ~ pops a value and calculate NOT and pushes the result. The only command to push constant values into the stack is the `. It pushes 13 values 33, 100, 108, 114, 111, 119, 32, 44, 111, 108, 108, 101, 72 in this order. The | prints all values in the stack to standard output. It is strongly recommended to use it only once at the tail of your code.

To print "Hello, world!", you just type two keys as below. It is the shortest code to print "Hello, world!" all over the world, except for HQ9+.

`|

KEMURI has many advantages. It can print any character, which HQ9+ can't. It has only 6 commands so it is easier to learn Brainf*ck.

"l"(small L) and "*"(asterisk) are reserved for possibility to use as a command "Execute the stack as Brainf*ck" in future.

I wrote a KEMURI interpreter in Python.

class Kemuri(list):
    def push(self, x):
        self.append(x)

    def do(self, com):
        if com == "~":
            self.push(~self.pop())
        elif com == "^":
            x = self.pop()
            y = self.pop()
            self.push(x ^ y)
        elif com == '"':
            x = self.pop()
            self.push(x)
            self.push(x)
        elif com == "'": # xyz => yzx
            x = self.pop()
            y = self.pop()
            z = self.pop()
            self.push(x)
            self.push(z)
            self.push(y)
        elif com == "`":
            s = list("Hello, world!")
            s.reverse()
            for c in s:
                self.push(ord(c))
        elif com == "|":
            result = ""
            while len(self) > 0:
                result += chr(self.pop() % 256)

            print result

        elif len(com) > 1:
            for c in com:
                self.do(c)

        return self
            
    def inter(self):
        while True:
            code = raw_input("KEMURI> ")
            if code == "":
                break
            self.do(code)

if __name__ == "__main__":
    Kemuri().inter()

日記

ローズマリーのシネオールってなんだっけと思ったら、ユーカリの香りの主成分ですね。そしてローズマリーって軟膏みたいなにおいだと思ったら主成分がカンファー・シネオールなんて書いてある。

カンファーは樟脳で、クスノキに多く含まれる。シネオールはユーカリや月桂樹に含まれる。他にピネンも含まれているけど、これはテレピン油(マツ科の樹木から取った製油)の主成分。うわー。ローズマリーって名前の「ローズ」から勝手に花系の香りを連想していたけど、思いっきり樹木系じゃん。

そしてこれにブレンドしたのがヒノキとジュニパー(Juniper - Wikipedia, the free encyclopedia)。思いっきり樹木。

でもこれをかぐと脳の中のもやもやがすっきりするんです。昨日、アロマショップから漂う香りに引かれて買ってきました。

なるほど、こういうのはウッディな香りっていうのか。

あと最近、疲労と取る効果があるとか喧伝されている青葉アルコールはシス-3-ヘキサノールらしい。ゼラニウムの精油に含まれているとか、スミレの精油に含まれているとか書いてあったけども裏は取れていない。青臭い香り自体はグリーンノートと呼ぶのがアロマテラピストっぽいらしい


__ とかそんなことを調べながら10時にかかってくるはずだった電話を待っているのにまだかかってこない。むー。

この前も12時にあう約束だったのに半時間以上送れて来たしなぁ。 こういう細かな約束を守れないと社会人としての信用を失いますね。

ごめんなさい、人のこと言えません。僕も頑張ります(ぉ


__ 秋元@サイボウズ研究所プログラマーBlog: iHack - 脆弱なHTMLフォームの突破ゲームで紹介されているiHackが面白いのでおすすめです。 ただし仕事をしているブラウザがタブブラウザの場合は別のブラウザを立ち上げることをおすすめします(というか仕事中にやるなって?)。リンク先を見て、Level1がものすごく簡単だ、とLevel2に進んだ瞬間、無限ループでalertするページで他のタブに移れなくなりました(^^;。IEを立ち上げてview-sourceしようとしたらいつの間にか使えなくなっていて(XPのSP2かららしい)びっくり。

そんなこんなでLevel3までは到達できたのだけど、Level3はどうすればクリアできるのでしょうか。ブルートフォース以外の方法が思いつかない…。


__ シャープペンシルみたいな形で、先はボールペンで、後ろのキャップを外すと中にアロマオイルを仕込めるような物が欲しい。仕事に疲れたらキャップを外して香りをかぐの。


__ Matzにっき(2006-09-15)

hama (2006-09-23 16:05)

真のAIを実現するプログラミング言語があるとしたら、 それはLispかLisp的なものだと思いません?

まつもと (2006-09-23 17:41)

思いませんね。> 真のAIの実装言語 真のAIのコアがどんな言語で実装させるか想像も付きませんが、Lisp(的)でなければならない理由はあまり思いつきません。Lispは素敵な機能がテンコ盛りの言語ではありますが、生産性の少々の違いはともかく、普通の言語でしょう。 むしろ、真のAIの本質は(将来存在できるとしたら)、様々な経験を通じた学習でしょうし、それはいかなるプログラミング言語とも関係ないでしょう。J・P・ホーガン「未来の二つの顔」参照。

僕が考える、「真の(またはそれにより近い)AI」は、新しいマシン(細胞)を買ってきて、TrueAI_OSをインストールして他のマシンとIP reachableにしておくと、勝手にネットワークを形成して、全体として一つの知性体として動くようなもの。外部の知性体(例えば人間)とのプロトコルはもちろん相手の知性体の一番使いやすい物をつかう(日本人なら日本語ね)。Lispを使うのは「よりすぐれた知性体である人間様が、より劣った知性体であるコンピュータにわかりやすいように構文木を直接書き下してやる」と言っているような物で、人間の方が上位だから真のAIとは認めたくない。真のAIは人間よりも優れているのだ。

で、現在その真のAIに一番近いものがGoogleなのです。ほら、人間の出力した自然言語の文章を読んで、人間と自然言語に近いプロトコルで対話してるでしょ。毎日いくつもの細胞(マシン)が死滅していて、しかもそれ以上のスピードで新しい細胞(マシン)を追加しているあたりとかまさに生命。


__ 書類書き終わった。 眠い。 自転車乗ってこよう。


__ 昨日と同じくらいの時間に昨日と同じ店に行ったのだけど、平日なのでもう閉まってましたorz

しょんぼりして帰ってきたら おびなたのはてな日記 - KEMURIコンパイラ が出来ていたw

mixiのKEMURIコミュニティまで出来ていたのでとりあえず入ってみたw

ちょっと元気が出たかも。

で、英語版の紹介記事を作ったw 西尾泰和のブログ: KEMURI


__ 調子に乗って西尾泰和のブログ: How to write oneliner in Python?まで作ってしまった。さすがに3時間がかかった。明日10時に秋葉原で打ち合わせなのになー。8時間寝たらぎりぎりじゃん…。せっかくお酒飲んで寝ようと思ったのに、完全にさめちゃったよ…。


__ Python Developers Camp 2006夏のライトニングトークでワンライナーの話をするとして、LLRingどまりだとLLRingに行った人がつまらないし、新しいPython Oneliner CompressedやBrainf*ck Interpreter in Python Oneliner Compressedを話すとしたらたぶんBrainf*ckの説明を入れる必要が出てくるだろう。やっぱりばっさり割愛してJythonの話だけにしよう。


__ とりあえず一番大きな仕事を片付けたので、明日から何をするかは明日きちんとメタ仕事して決めよう。選択肢は3つくらいあるなぁ。

2006年09月24日

GRINEditドキュメントの種

将来ドキュメントを書くときに使えそうな文章をためておく場所です。

GRINEdit用語集

  • MouseOperation:各種マウス操作を受け持つクラス、またはそのオブジェクト。MouseOperationクラスの子クラスである。

よくある失敗、FAQ

  • AddVertexではなくてaddVertex。基本的にメソッド(関数)の名前は頭が小文字、"CircleVertex"などのクラス(物の種類)の名前は頭が大文字
  • addVertexなどの1番目の引数は文字列。addVertex(CircleVertex, {})ではなくaddVertex("CircleVertex", {})

maven

IT-Walker on hatenaを参考にしてmavenのpom.xmlに<addClasspath>true</addClasspath>と書き足す。

試験管のなかのコード :: Maven2 で JAR の Manifest ファイルを設定する方法をメモを参考にして<classpathPrefix>dependency</classpathPrefix>と指定してやればよいようです。

Eclipseとの連携 Maven -TECHSCORE-を参考にしてM2_REPOに正しい値を入れたらEclipseでもビルドが通るようになりました。

コマンドラインで「mvn dependency:copy-dependencies」とやってみたらtargetフォルダの中にdependencyフォルダが生成され、中にはjarファイルが入っていました。うまく動いたようです。

SWTの新しいライブラリはmaven2のリポジトリに入っていないので、 SWTのサイトからダウンロードして展開し、jarはローカルリポジトリに、 dllは/src/main/resourceに入れる。 Eclipse側では/src/main/resourceを実行時の作業ディレクトリに指定する。

設計

grinedit_structure.png

左がGRINEdit0.10時点の設計、右がGRINEdit0.20で目指す設計です。 XML-RPCやJythonなどいろいろな方法でアクセスできるようにする上で、そのそれぞれに違う入り口を作っていたのでは大変なことになるので一つにまとめようという発想です。そうしておかないと「Jythonで頂点を追加するのは~~~だけど、これはまだXML-RPCではサポートされていないから古い~~を使ってね」なんていうダメダメな事態が発生しそうだからです。一方で、JavaやJythonなどの「Javaオブジェクトに直接さわれる方法」で操作したい人にとっては、間にクッションが入ってしまうともどかしいので、より直接的にいじることが出来る方法を提供します。

基本的にXML-RPCから追加できるすべてのオブジェクトは文字列型のnameというフィールドを持っています。addVertexなどのadd*系メソッドは新しいオブジェクトを作成してそのnameを返します。nameはシステム側が一意になるように振ります。ただし人間の可読性のためにプレフィクスをつけます。addVertexするとVertexというプレフィクスがつきます。

getObjects("Vertex")で頂点の一覧が名前とパラメータのマッピングとして取得できます

log

西尾泰和のブログ: 日記から移動。

JSON形式での保存と読み込みのテスト。 頂点と辺はきちんと復元されることを確認。 たしか追加で入れた物理法則が再現されない状態だったはず。 頂点のアンカーは外れてしまうことを確認。

使い勝手の悪い、コンソールでコマンドを入力するタイプだけども、一応マインドマップを作って保存/読み込みできる。

「ゆるいバネ」を作ろうかな。自然長以上に引っ張ったときは引力を発生させるけど、逆に圧縮されたときは反発しない。あと一定以上に強く引っ張られたらへたって引力が弱くなる。あー、でも一度へたってしまっても、しばらく近づけておいておくとだんだん元に戻って欲しいなぁ。その方が気持ちいいはず。

InvocationTargetExceptionはタイミングの問題で発生するようだ。 InvocationTargetException (Java 2 プラットフォーム SE v1.4.0) ラップされた例外だそうなので、中身を表示させる。

ああ、boundか…。 現状では頂点を作成したときにboundはnullになっていて、 renderが呼ばれた場合にboundがnullなら再計算する仕組みになっています。 これはboundの計算にグラフィックコンテキストが必要だからです。で、タイミングの問題で、普段は十分に描画が早いためにaddVertexとgetParamsの間にrenderの呼び出しが入るためにboundがnullではなくなるのですが、早いプログラムで一気に頂点を足した場合に稀にrenderが呼ばれる前にgetParamsが呼ばれてしまい、nullをVectorに変換しようとしてNullPointerExceptionを投げているわけです。さて、どうしましょうか。

  • boundをnullではない値で初期化する。[-1, -1]とか。
  • 変換メソッドの中で返すべき値がnullの場合に代わりに何か返す。
    • ユーザが「失敗したこと」に気づかずにその値を使って、正だと思っていた値が負だったりして面倒なバグを引き起こしそう。
  • NullPointerExceptionを投げる。XML-RPCのクエリを投げた側はその例外を受け取ってうまく行かなかったことを知る。
    • java.lang.NullPointerException
      	at org.nishiohirokazu.grinEdit.UtilCast.point2Vector(UtilCast.java:150)
      	at org.nishiohirokazu.graph.BoxVertex.getParams(BoxVertex.java:62)
      
      と言われて、Javaのソースを見ないと原因がわからない。
  • っていうか今positionの値が必要なだけなのに全部のパラメータをまとめて返してくるAPIが悪いんじゃない?
    • まぁ、今フィールドの数だけsetterがあるのに、さらにgetterも作ることになるけど…まぁ、これはやるべきことかも。
      • 面倒だからsetter/getter生成スクリプトをPythonで書く。
    • これをやっても、やっぱりboundの値をユーザが取得しようとして失敗する可能性は残っているから今回の問題の本質的な解決にはなってない。
    • 明日デモするプログラムにそんな広い範囲の修正は掛けたくない。
      • とりあえず今日はboundの値を返すコードだけコメントアウトでいいんじゃない?セーブ/ロード時にboundの値が欠けるけど、欠けたら自動的に再計算されるわけだし。

座標をデフォルトの値に戻すコマンドが欲しいかも。

たかだか300頂点で15FPSまで落ちてしまうことがある。長い紐状のグラフがぐるぐる巻きの状態になってしまったときに、外側の頂点の拡散を辺の引っ張る力が邪魔をするために、頂点が密集した負荷の高い状態が持続してしまう現象。

デフォルトの物理演算は、イヤならはがせるわけだから、機能てんこ盛り路線でいいのかも。それなら「反発力がなかなか減らないときには拡散を加速する」という物理法則を入れる手がある。

log

GRINEditの過去のログを読んでダイジェスト版を作ろうと思ったのですが、想像以上に一杯でうまく整理できていません。

プラグインのON/OFF、「プラグインを入れるときに読み込むプラグインを設定に書き加える」という選択肢は「解凍してフォルダーにコピーするだけで!」と言えなくなるのでイヤだったのだけど、発想を転換すれば両方出来ることに気がつきました。つまり「無視するプラグイン」という設定ファイルを作るのです。コピーした時点でデフォルトONで、もし一時的にOFFしたければ無視するプラグインファイルに書き足せばいい。

書き殴り文章、箇条書き、きちんとした文章、高橋メソッドのプレゼン、箇条書きのプレゼン、箇条書き風のマインドマップ、グラフ上のマインドマップ(ブレインダンプ?)、などなどを、相互に変換できるといいなぁ。

文章で書き殴っているときと箇条書きで書き殴っているときとあるけど、 本当はグラフで書き殴りたい。

JavaのリフレクションでメソッドにくっついているJavadocコメント取れるかな。取れそうな気がする。取れるんだったらJavadocに頼らないでももっと楽しいことが出来るよね。

無理っぽいなぁ。残念。Javadocはソースコードをパースしているんだろうか。例えばhogeというメソッドの説明はHashtable docHogeに{"ja": "日本語の説明", "en": "English description"}なんて感じで入れる、なんてのはJavaで書くのは面倒だよねぇ…。Javaで文字列の中で改行したらどうなるんだっけ。あー、Eclipseが勝手に+で繋いでくれる。ふむふむString docHoge = "@ja: 日本語の説明 @en: English description";ならOKだろうか。

文章での殴り書きは、後から読み直して「いや、それは違うだろう」とつっこんでキャンセルしやすい。箇条書きにしてしまうと理由なしにしなければ行けないことに見えてしまってキャンセルしにくい。そういう問題点。

箇条書きにする際に、やることだけを書くのではなく「なぜそれをやる必要があると思ったか」を書けば済む話?

西尾泰和のブログ: TODO がすごいことになってしまった。把握できない。

CPANのようなライブラリを作って、GRINEditプラグインを登録・検索できるようにしよう、と考えて、じゃぁドキュメントもプラグインから自動生成して検索対象にしたらいいんじゃないかと気がついた。

はっ、レンダリングの順番の問題、今はまず辺を書いてから頂点を書く、という決めうちだけど、ここがカスタマイズできれば全て解決するのではないか。XML-RPCで。グループごとにZオーダーを指定できればいろいろな問題が全て解決するのでは。 そうするとアンカーされた頂点にピン留めマークをつけるってのも、頂点クラスをいじるのではなく、アンカー物理演算に頂点より前でアンカーしている座標にピンの絵を描けばいいだけ。おー、シンプル。美しい。これが正解に違いない!

でも一応、今のバージョンを上書きするのではなく共存できるようにするためには…。 いまメインループ内でgraph.renderを呼んでいるのを、レンダリングエンジンオブジェクトのrenderを呼ぶようにして、Graph#renderをそっちに移して、CommonGatewayからそれを変更できるようにして、init.pyからそれを設定するようにすればOKかな。

今気づいたけど、makeTableとかvertexDictとか、名前に混乱が見られる。実態はHashtableだけど、抽象的にはMap。

UtilXMLRPC#makeObjForNameがMediatorに移ればいいのでは。移した。

間違い。 SubversionでRevert。右クリックして選ぶだけ。やりなおしも超簡単。

正しくは、UtilXMLRPC#makeObjForNameがMediatorに移動するのではなく、文字列からクラスオブジェクトを返す処理だけをMediatorに移すのだ。 名前はloadClassでいいかなー。

もう28時だ。エンバグしそうなので寝よう。

日記

Could It Be A Big World After All?。抄訳&意訳なので正確を期す人は原文を読んでください。

Stanley Milgramの実験によって証明された「「知り合いの知り合いの…」とたった6回繰り返すだけですべての人がつながる」という理論は教養のある人の間ではもはや常識になっている。しかし、Milgramの論文とかをよく読んでみると、この理論は根拠に乏しく、それどころか例の実験結果はむしろ「我々の生きている社会は人種や階層の違いといった社会的な壁によって区切られている」ということを示唆している。

ちょっ、w。

続き:

この論文で私は、「我々はたかだか6回知人をたどるだけでつながりあう『小さな世界』に住んでいる」という愉快な考えは、もしかすると学術的にはただの都市伝説かもしれない、と主張する。要点は下記
  • Milgramの「小さな世界」に関する出版物は、他の研究者によって追試がされていない。さらに、私がエール大学の図書館から見つけたMilgramの論文に載っている、出版されていない「最初のSmallWolrd実験」は「人々は6回でつながる」という有名な解釈の根拠としては不十分である。一言で言えば、一つの市に収まらないような実験は、ほとんど鎖が完成していない。
  • 「人々は6回でつながる」という考えの驚くべき受け入れられ具合は、それ自身心理学者にとって興味深い現象である。なぜこのような直感に反する発見がこうもたやすく受け入れられるのか。そして、このことは我々の理性がどうやって働くのかについて何を教えてくれるのだろうか。
  • 数学をはじめ、病気の流行から神経科学まで広い分野で"small world problem"が見直されている。 この引き金を引いたのはsmall worldの概念に数学的な基礎付けを提案したWatts & StrogatzのNature論文である。 学術およびメディアの関心は高まっているが、"small world problem"はすでに心理学の分野に落ちている。つまり、数学者が無視するような、認知や感情の問題を扱う分野だ。

個人的には、一時期この思想は面白いと思って色々シミュレーションもしてみたんですけど、色々よくわからない所があったのでほりだしてしまいました。まず平均パス長がなぜか加算平均を使っているので、グラフが連結していないとそもそも平均パス長を求められない点が謎。なんで調和平均を使わないのか。あと、非連結だと平均パス長が求められないから、とか言って連結なグラフだけ取り出したらすでにランダムグラフじゃないじゃないか、とか。そもそもそのランダムグラフの作り方だと同型なグラフを何度も数えていて、グラフの形によって重複して数えられる回数が異なるから平均が偏るじゃん、とか。そもそも「多くのグラフにSmallWorld性があって、ランダムグラフとレギュラーグラフにはない」のじゃなくて「ランダムグラフとレギュラーグラフには逆の特徴があり、そのほかのグラフはその間にある」ってだけじゃないのか、とか、ランダムグラフが離散距離空間上の点の分布に距離に応じた確率で辺を張った物と考えて、もっと一般的な距離空間上でSmallWorld性が出るか出ないか見るべきじゃないか、とか、そもそもSmallWorld性の有無はどうやって定量的に評価するんだ?とか色々考えたのですよ。ちなみに、上に書いたようなことはきちんと勉強してない一介の学生が隅っこでぼやいていただけのことなのでまじめに研究している人の成果を否定する物ではありません。

やはり有る物を否定する作業は嫌がる人が多く喜ぶ人は少ないので楽しくない。ない物を作り出す方がみんな喜んでくれるからやりがいがもてる。人生の時間は限られているので幸せな方をやりたいなぁ、と思ったわけです。それが僕がSmallWorld性の研究を進めなかった理由。


__ 眠い。

How to make Python OnelinerとかBrainf*ck Interpreter in Python OnelinerとかKEMURIとか英語の記事を書くべきですよね。 広報上。上みたいな適当な和訳している場合じゃないですよね。


__ 今日、たまたま笠井正博 - Google イメージ検索という人の作品を見たのだけど、なんかこういうのいいね。どうやったらコンピュータで自動生成できるか考えてしまう(ぉ)

実は冗談ではなくて、本気です。

そうか、インタラクティブ性がなかったのがいけないんだ。単純なランダムではなく、物理法則に従った規則性があり、かつ規則だけではない揺らぎがある、というところまではインタラクティブ性がなくても可能だけども、そこにインタラクティブ性が入ることで「ゆらぎ+規則性+人間の意図」という三位一体の攻撃が出来るわけですな。やった。これGRINEditで(ぇ)

GRINEditの今は白に固定されている背景色を変えられるようにして、 半透明頂点を実装して、合成が加算になるようにすればいいんだよね。(本気)

Java 2D による半透明描画

出来そう。

Pythonで指定したディレクトリの中を再帰的にdiff

Pythonで、指定した二つのフォルダの中身を全部比較して変更されたところを表示するスクリプトを書いてみましたが、diffに-rというずばりそういうことをするためのオプションがありましたorz

とりあえず、なんかの参考になるかも知れないので載せておきます。あと、これは「新しいプロジェクト」ディレクトリ内になくて「古いプロジェクト」ディレクトリ内にあるファイルは無視します。僕はそれでよかったので。diff -rの挙動がどうなのかは調べていません。

#
# diff between old project and new project
#

import difflib, os, sys
diff = difflib.Differ()

OLD_PATH = r"C:\Home\workspace\rel-visualizer\GRINEditAlpha\src" 
NEW_PATH = r"C:\Home\workspace\grinedit-app\src\main\java"

def getNewPath(path):
    return os.path.join(NEW_PATH, path)

def getOldPath(path):
    return os.path.join(OLD_PATH, path)

for (root, dirs, files) in os.walk(NEW_PATH):
    p = root[len(NEW_PATH)+1:]
    for filename in files:
        path = os.path.join(p, filename)

        data = os.popen(r"c:\cygwin\bin\diff %s %s" % (
            getOldPath(path),
            getNewPath(path))).read()

        if data != "":
            print path        
            print data

2006年09月23日

日記

もやもやして仕事がはかどらない日。

いつものことだとか言わないで!


__ 「リモートリポジトリにないJarをローカルリポジトリに入れる方法」という文章は「りもTABにないJarをろーTABに入れる方法」と書ける。ATOKの補完機能で。ATOKユーザがなでしこでプログラムを書くと変数とか補完できてうれしいのかも知れない。というか僕も試しにPythonのコードをATOKオンで書いてみるか…ダメだ、インデントするのにTAB使ってるからどっちかのキーアサインを変えないと。


__ 不安に負けそう。


__ 僕なんかに出来るのかなぁ、という不安がふくらむ一方。

力を尽くして狭き門より入れ>自分


__ 6.2 os.path -- 共通のパス名操作

パスがシンボリックリンクを含んでいるかによって意味が変わることに注意してください。

11.1 os.path -- Common pathname manipulations

It should be understood that this may change the meaning of the path if it contains symbolic links!

「パスがシンボリックリンクを含んでいる場合には、この操作によってパスの意味が変わってしまうかも知れないということに注意してください。」 ですかな。 もっと言えば 「パスがシンボリックリンクを含んでいる場合には、この操作によってパスの意味が変わりうるということを理解して使うべきです。」なんだけど、日本語としてはあんまりそういう激しい言い方はしないかな、と。


__ ブラウザ上で、本文の左や右にメニューが入っているせいで本文の幅が短くてディスプレイを有効活用できていないページをワンクリックで全画面表示にしたい。さらにワンボタンできれいに1ページずつめくりたい。さらに、同じ体裁でいくつものページに分かれていたらそれも全画面表示したい。

bookmark this

JavaWorld Online - J2SE 5.0の新機能 ――第4回 Javaのprintfとかで試してみてください。あー。marginが設定されていると、marginの分だけはみ出すのか…。あとこのブログみたいに背景色が濃い場合は背景と文字とのコントラストが低くて読みにくい。背景は薄緑固定でもいいのかなぁ。

log

grinedit_structure.png

左がGRINEdit0.10時点の設計、右がGRINEdit0.20で目指す設計です。 XML-RPCやJythonなどいろいろな方法でアクセスできるようにする上で、そのそれぞれに違う入り口を作っていたのでは大変なことになるので一つにまとめようという発想です。そうしておかないと「Jythonで頂点を追加するのは~~~だけど、これはまだXML-RPCではサポートされていないから古い~~を使ってね」なんていうダメダメな事態が発生しそうだからです。一方で、JavaやJythonなどの「Javaオブジェクトに直接さわれる方法」で操作したい人にとっては、間にクッションが入ってしまうともどかしいので、より直接的にいじることが出来る方法を提供します。


__ Eclipseとの連携 Maven -TECHSCORE-を参考にしてM2_REPOに正しい値を入れたらEclipseでもビルドが通るようになりました。

あー、あとswtがmavenでjarを入手できるちょっと古いバージョンだと3.0系のdllを要求して起動できないので、そこをどうにかしないと行けない。EclipseのサイトからDLしてきた物をローカルリポジトリに入れればいいのか。

射撃しつつ前転 - 情報科学若手の会

GRINEditを見ていて、制約解消にちょっと興味を持った。

僕も興味があります。教えてください(ぇ)

冗談はさておき、制約解消はGRINEditの肝でありながら、一番自信のないところでもあります。将来的にこの肝の設計がまずかったことに気がついたらどうしよう。

僕が自分のサーバにmavenのしきたりに則った形でgrineditのjarを置いて、プラグイン開発者の方にはmavenのミラーの設定で僕のサーバを指してもらえばいいのかな?

あー、動的リンクされたライブラリからJythonでうまくimportできていない問題。どうしよう。

プロジェクトルートにswt.dllをコピーしてEclipseからも実行できるようになった。そのままでは実行時に(本来ExecutableJarと同じ場所にあるべき)config.pyを見つけられないので/src/main/resourceを実行時の作業ディレクトリに指定してみた。動いた。

Eclipseから起動したときには「Jythonからorg.eclipseのインポート」がきちんと出来、maven2.0でExecutableJarにしてswt.jarへはMANIFEST.MFのClass-Pathで指定した場合はうまく動かない。MANIFEST.MFはmavenが生成した物なのでつづり間違いなどの可能性はないだろう。そもそもメニューを生成するinitMenu.py内でのインポートに失敗しているだけで、Java側で生成するShellは表示されているわけだから。極めてやっかいな問題だ。どうしたらこんな現象が起こる?「MANIFEST.MFのClass-Pathに指定されている外部のJarは実行時に必要になったときに初めてロードされる仕組みになっており、かつJythonは自分のインスタンシエイトされたときにすでにロードされていたクラスしかインポートできない」とか。違うな…インスタンシエイトの時点ですでにSWTのShellが作られている…。

根本的な解決はとても難しそうだけど、対症療法は非常に簡単。 Javaの側でインポートは出来ているのでそのインポートしたオブジェクトをPythonInterpreterにsetしてやれば済む。ちゃんと動いた。 やだなぁ、対症療法。すっきりしないなぁ。

Maven対応のプロジェクトでEclipse側での実行と、「mvn package」を使ったExecutableJarの作成・実行の両方が出来るようになったので、こちらのプロジェクトを本流にしようと思います。さて。古い方のプロジェクトとこっちのプロジェクトのdiffをどうやって取ろう。西尾泰和のブログ: Pythonで指定したディレクトリの中を再帰的にdiff

dllはsrc/main/resourceの中に入れておいて、Eclipseの実行の設定で/src/main/resourceを実行時の作業ディレクトリに指定する。プロジェクトのルートに置く必要はない。

よーし、移行完了。 すっきりした。 これで、少なくとも古いプロジェクトの方で情報科学若手の会時点のデモは可能。あとsubversionで管理もしてみた。古いプロジェクトのAntはjarを作ってスクリプトやサンプルデータを、いらない物や公開しちゃ行けないデータを取り除きつつ適切にコピーしてくれて、ダブルクリックして動くことを確認してからzipで圧縮するだけでリリースできる状態にまでしてくれてたけど、今のmavenはjarを作るだけなので、前やっていたことまで出来るようにしよう。

CommonGatewayのaddVertexなどのメソッドは全部addObjectなどを呼び出すようになった。modVertexが呼び出すメソッドがmodObjectじゃなくてmodifyなのはやっぱダメかな。

modObjectに変えた。

眠い。

2006年09月22日

日記

スラッシュドット ジャパン | 「♂用ターゲット」ポイント搭載のトイレ経由で[生活全般]----朝勃ち時の排尿方法----。面白おかしい。758(745)が一番実際に近いかもなぁ。でもこの方法で失敗して朝からトイレ掃除をするハメになった悲しい経験が…。


__ 今日は12時に人に会う約束。 でももう12時17分。迷ってるのかな?


__ かるた ラーメンズかるた?(ラーメンズ) 復刊リクエスト投票。 わくわく。


__ 口内炎が酷い。 3時に寝て9時に起きて12時に人が来るのを待って1時に来てちょっと話して、なぜかすごく疲れたので昼寝したら18時半!な、なんだってー!

一般人向けに、裏に数独の入っていない名刺も作るべきだと思った。

やらないと行けないことがあると生産性が下がり、やりたいことをやっていると生産性が上がるのはもう分かり切ったこと。


__ 高木浩光@自宅の日記 - 「リンクお断りは普通」と人の心に種を蒔くAC

こういうのをやるには心の強さが必要なんだろうなぁ。 ちょうどこれを呼んでいるときに大阪の聞いたこともないアパレルショップからオープニングキャンペーンのお知らせとか言って僕の携帯に電話がかかってきたのですが、精神の平穏を保って会話することが出来ませんでした。やれやれ。大体、これがメールのやりとりとかならじっくり考えられるからいいけど、口頭だとしゃべることで頭がいっぱいになってしまう。


__ Nova 1 photo selection。 すごい、つくりたい。


__ Guym-network - 秋葉原で警察に捕まりました-真概夢戯言/2005-12-01-Wiki。 今知りました。これはひどい。


__ ビルドに時間のかかる作業をしていると、その間作業が出来ないから時間がもったいないなぁ。 やっぱりもう一台マシンがあった方がいいのかもなぁ。

2006年09月21日

日記

Revenge of the Nerdsよりグリーンスパンの第十法則(リンク先では第10規則と書かれているけど)。

全ての十分に複雑なCもしくはFortranプログラムは、後付けの、不完全な仕様とバグを持ち、遅い、Common Lispの半分の実装を含んでいる。

GRINEditにも後付の名前空間とかプラグインという形での不完全な関数定義とかを含んでいる気がします。でもCommonLispにしたら解決するかと言われるとそれも微妙なような。


__ ちなみに普通「法則」はlawなのでtenth ruleは第10規則でいいのですが、 実際の中身が規則っぽくないので不審に思って調べてみたところ、 どうも第1~第9はなくていきなり第10からあるみたいです。グリーンスパンの法則は。ジョークとして発言するときに「~するための10のルール」とかと混ざったのかな。


__ Yahoo本社でDELLノート爆発、数百人が避難 - Engadget Japanese。こわい。ソニーVAIOノートも炎上 - Engadget Japanese。ソニーのも炎上してたんだね。怖い。バッテリーが炎上したら、とりあえず水はかけちゃダメで、そこら辺に置いてある消火器は一応電気火災対応だから使ってもOKで、だけど消してもまた火が付いてしまうだけらしい。外にほりだすしか。で、ハードディスクの中身はやっぱりサルベージ不可能なんでしょうか?


__ 脳の中のアイデアの一番プリミティブな形状は親や子の区別のない単純なネットワークだと思います。それを整理することで階層状のツリーにすることが出来ます。トニー=ブザンのマインドマップはすでに階層状になっている時点でプリミティブではありません。一度考えて整理しないとああは描けません。彼の「右脳と左脳をバランス良く働かせる」という目標には賛同しますが、マインドマップが脳の中身を最初に描く形式として適切だとは思いません。

でマインドマップという言葉は彼が作った物だから、「よりプリミティブなネットワーク状の表現方法」をマインドマップと呼ぶのはよくないですね…。マインドネットワークとかにしましょうか?


__ Eclipseプラグイン・アーキテクチャーに関するノート。 後で読む。


__ Mind Graph : graphic language to solve problems - screenshot.Mind-Graph : mind-mapping, problem-solving, note-taking, etc


__ Welcome - usbcell.com 。ちょっw


__ ( ó㉨ò)しょぼーん。(´・ω・`)しょぼーん。´( ó㉨ò)`おっ、これいい感じかも。あー、フォントによっては耳が短いなぁ。( ó_ò)

2006年09月20日

log

JSONパーサをmavenで落とせる物に変えてみる(また地味なことしてる…)antlrとlexerの違いを調べる。

よくわからないのでJSONPaeserAntlrを使ってみる。…使い方がさっぱり。 json.simpleは簡単だったのになぁ。

むしろ今のところJSONはJSON形式で読み書きするときにしか使わないから大したパフォーマンスは要求されない…。Jythonでいい気もしてきた。 とりあえず今回の発表でもわかったけど、JSON形式での保存、読み込みは今のところプレゼンするほどの物ではない。物理演算まできちんとシリアライズできるようにしたら?うーん? ネットワークの同期をデモするなら、色々いじった後JSONでエクスポートをして別ので読んだら同じ形です、じゃ面白くないし。

ああ、ローカルのGRINEditで保存した物をFTPでサーバにアップロードしたら、ウェブページ上のアプレットでも同じ物が見える、と。

PythonからXML-RPCで頂点と辺の情報を取得して、その情報から同じ形のグラフを再現することが出来ました。これでいいなぁ。JSON使わなくてもユーザが任意の形式でシリアライズできる。

ただこの場合はシリアライズ前のグラフとシリアライズ後のグラフで内部で振られているnameフィールドの値は異なってしまう。将来的に何か問題を起こしそうな気はするけど、逆にこれでいいのかも知れないという気もする。一意でないと行けないnameフィールドを元通りに復元するなら、グラフのマージとかはできないわけで、元通りに復元しないことを前提として頂点のnameがどう変わったかの対応付けをするようにしたほうが結果的に色々いいかもしれない。その辺はわからない。眠い。

この前作りかけた入れ子頂点は親と子の位置がかっちり固定されていたけどその必要はない。むしろ子供の頂点が動けるもっとゆるい入れ子の方がいい。まるくて、中にはいるべき頂点の重心が自分の中心であり、最も遠い頂点までの距離*1.1くらいが半径であり、中に入るべき頂点には中心からの距離に比例した引力を持ち、中にはいるべきでない頂点には半径*1.1以内に入らない制約。つつむ頂点の中に入っている普通の頂点は引力で緩やかに拘束されつつ外の頂点との辺による引力で位置を変えたりする。

いくつかの頂点が複数の親に属しているとベン図みたいになるのかな。これはUIがちょっと難しそう。

PythonのxmlrpclibでGRINEditから文字列を取得するとUnicodeで返ってくるのに、GRINEditにUnicode文字列を投げると化けてSJISならOK。xmlrpclibが余計なことをしているのかな??投げるときに....encode("sjis")とやればいいだけではあるけど。

Python Unit Testing Framework (in Japanese)

特定のモードの時にマウスアイコンが変化してほしい?マウスアイコンを消してマウスに付いてくる頂点?

頂点は物理演算になれないが、でも描画したい物理演算もある。 そもそも最近の「それ頂点でできるんじゃね」の流れを見ていると、 頂点と呼んでいた物は実は「インターフェイスIRenderableを実装したクラス」でいいのではないかという気も。辺もIRenderable。あ、でも辺の接続する頂点として辺を指定されるとイヤ…でもないのか…うーん。追加できないのがイヤという可能性もある。

2006年09月19日

日記

有機EL搭載ミニキーボード発売。笑った。なんでスコア0なんだろう。

生まれてこなかった双子の男兄弟の細胞が成人した女性の体内に生き続けているケースがあるそうだ。驚き。


__ 気分が悪い。 胃が。 少し寒気もする。上着持ってくるの忘れた。


__ GRINEdit、キャンバスのサイズを変更したときに、最初のスクリーンの中心に対して拡大縮小されていたのを、きちんと現在のキャンバスの中心に対して拡大縮小するようになおしました。


__ 眉毛むしってしまうクセが再発。むしるのは左手なので右の脇はすでにほとんど脱毛されてしまいました。あ、だから眉に行ったのか。


__ ウノウラボ Unoh Labs: 国際派エンジニアになるための道のり

このブログは持ち回りで書いていて、はてなブックマーク数を競っていたりもするわけで、

それなかなか面白い。

でも今見たら問題の記事は1137ユーザがブックマークしていたので巻き返しは難しそう。


__ 野菜。野菜。 アスパラが70円。ただし穂の部分がない。非常に怪しい。アスパラは古くなると穂のところが伸びてまばらになるからね。でも70円だったので買ってきました。古くなって繊維質になっていることを懸念して、短めに刻んでベーコンビッツと一緒に炒めてみたけど、別にそんなに堅くはなっていなかった。 新しいキムチを買ってきたつもりが、家にあるのと同じ物だった(´・ω・`)。 ニンジンをイチョウに切ったり厚さ1ミリの輪切りにしてみたり。レンジで加熱。冷めたらこの買ってきたキムチと混ぜてしばらく熟成する予定。

料理しただけで眠くなってしまった。


__ 危ない。検索して「東京から新富士まで近いと思ったのに飛行機に乗るのかぁ」と思ったら北海道の新富士だった。乗り換え案内の目的地が複数出ていることに全く気づいていないことが判明。


__ GRINEditのTODOを最新の状態に更新しないと。

生産性が低下しているからさっさと寝て明日作業した方がいいのかも知れない。

log

GRINEditに入れた頂点を投げる機能は微妙。 1つの頂点だったら自然に動くけども、 ネットワークの一部をつかんで投げた場合、最初に引っ張ったバネの引力で頂点が戻ってからゆるゆると後ろのネットワークを引きずりながら動くので不自然。Anchorの位置を更新しながら移動して行くのの方が自然そう。

デモモードでは文字が大きいとかどうだろう。

Jythonコンソールで日本語を打つこと自体は出来るけど、頂点のラベルに日本語を指定すると化けますね。

(修正完了)コンソールでe.setDirected(1)してもエラーになるな。これは変換クラスが、Booleanを期待しているときにPyIntegerが渡されたときに処理できていないのが原因だろう。

(修正完了)e.setK(1)しても同様。Doubleが欲しいところにPyIntegerが来たときの処理がされていないのだろう。

動的にバネ係数をいじって遊んでいたら、案の定発散してしまったが、発散したときには処理を一時停止するようにしたほうがいいのかも。

そういえばメニューに「一時停止/解除」をまだつけていなかった。

Jythonコンソール、フォントサイズが変えられないねぇ。 作者に送ったパッチ、次の更新で採用しますって言ってたけどまだ次のバージョンになってないんだなぁ。たぶん作者はこのプロジェクトをサポートする気がないんだろうなぁ。他のコンソールもサーベイして、必要なら乗り換えよう。ReadlineSetup - JythonWiki

名前空間をフラットにする必要はないが、全部のオブジェクトが入っている名前空間があるべき。 grinedit.addObject("Vertex", "vertex1")みたいに名前で参照して追加できるように。

現在は選択された頂点はSelectionというレガシーなものに入っているけど、これをVertexやEdgeやLaw同様にHashtableに入れてXML-RPCからアクセスできるようにすべき。今はJavaとJythonからしかアクセスできない。

この両方をやったら grinedit.addObject("SelectedVertex", "vertex1")みたいな方法でXML-RPCから頂点の選択が出来る。

grinedit.newTable("Hoge")してgrinedit.addObjects("Hoge", ["v1", "v2", "v3", ... ])する?

XML-RPCのデモで、server.grineditが長いからと言うことでgrineditに代入して使っていたけども、画面は狭くてもったいないのでgに代入することにしてみた。Jythonの方の組み込み名前空間にもgrineditとgの両方を入れよう。

本体を起動するbatファイル、じゃなくて、本体を起動する実行可能Jar、というのがいいのかも。スプラッシュウィンドウを出して、出力された情報をそこに出せばいいわけだ。本体画面が表示された後で、"HIDE_SPLASH"とか出力して、ランチャー側はその文字列を見たら隠れればいいわけだ。エラーが起きた場合にはそのメッセージを出せばいいし。あー、これいいかも。

KEMURI

第39回情報科学若手の会の夜のセッションでのディスカッションから生まれた言語「KEMURI」を紹介します。

これはKEMURIで「Just Another Python Hacker,」と表示するコードです。

KEMURIはスタックマシンです。 スタックには0~255の値が積まれます。 1つの文字が1つの命令になっています。命令は全部で6つです。 「^」はスタックから2つの値を取り出し、XORを計算してスタックに積みます。「"」はスタックから1つの値を取り出し、その値を2つ積みます。つまりスタックの頭からxyzの順で並んでいたらxxyzにします。 「'」はスタックから3つの値x, y, zを取り出し、x, z, yの順で積みます。つまりスタックの頭からxyzの順で並んでいたらyzxの順に並び替えます。 「~」はスタックから1つの値を取り出し、NOTを計算してスタックに積みます。 定数値をスタックに積む唯一の命令は「`」で、これを実行するとスタックの上から順に「72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33」という値が入ります。 「|」はスタックの中身を標準出力に出力します。基本的にプログラムの最後で1度だけ使うことを推奨します。

「Hello, world!」と出力するコードは下のように簡潔な物になります。KEMURIはHQ9+に次いで2番目に「Hello, world!」を短く書ける言語です。

`|

NOTを使わずに、0~127の任意の文字を出力できることが知られています。

コーディングのコツ。 「"^^」でスタックの頭の1つの値を捨てることが出来ます。「^"^^」で2つ、「^^"^^」で3つ捨てることが出来ます。「'^"^^」で1番上の値を捨てずに2番目、3番目の値を捨てることが出来ます。

「l」(小文字L)と「*」(アスタリスク)は将来的に「スタックの中身をBrainf*ckとして実行」という命令に割り当てる可能性のために予約されています。(KEMURI_PLUS)

Pythonで書かれたKEMURIのインタープリタを下に掲載します。

class Kemuri(list):
    def push(self, x):
        self.append(x)

    def do(self, com):
        if com == "~":
            self.push(~self.pop())
        elif com == "^":
            x = self.pop()
            y = self.pop()
            self.push(x ^ y)
        elif com == '"':
            x = self.pop()
            self.push(x)
            self.push(x)
        elif com == "'": # xyz => yzx
            x = self.pop()
            y = self.pop()
            z = self.pop()
            self.push(x)
            self.push(z)
            self.push(y)
        elif com == "`":
            s = list("Hello, world!")
            s.reverse()
            for c in s:
                self.push(ord(c))
        elif com == "|":
            result = ""
            while len(self) > 0:
                result += chr(self.pop() % 256)

            print result

        elif len(com) > 1:
            for c in com:
                self.do(c)

        return self
            
    def inter(self):
        while True:
            code = raw_input("KEMURI> ")
            if code == "":
                break
            self.do(code)

if __name__ == "__main__":
    Kemuri().inter()

日記

おはようございます。5時起床。健康的。

情報科学若手の会(略してwktk)の夜のセッションで生まれたKEMURI についての説明を書きました。


__ 今朝ご飯を食べに行った店で「それが大事」がかかっていました。 この曲は確か小学5,6年生の時に担任の先生がかけたので知ったのですが、当時スポ根的な根性の歌だと思ってました。「負けないこと 投げ出さないこと 逃げ出さないこと 信じ抜くこと ダメになりそうなときそれが一番大事」だから。でも本当は「ここにあなたがいないのが寂しいのじゃなくて、ここにあなたがいないと思うことが寂しい、でも負けないこと(以下略」なんですねぇ。当時の僕はサビ以外の部分を全く理解していなかったようです。今改めて聞くと、普通に恋の歌に聞こえるのにねぇ。


__ 。なるほど、こうすればはてなブックマークの件数が表示されるのですね。 今度自分のMTにこの機能を入れようっと。


__ 思いつくままに書いた「限りなく透明に近いGRIN」と「なんとなく、Eclipse」は簡単に元ネタを調べられたけども、ひねってない「空虚な私」と「心の隙間埋めてください」の元ネタが見つけられない罠。というか書いて発表してから元ネタを後付けするのはどうかと…>自分。

気になるので人力検索にかけてみた(ぇ)


__ 今日は久しぶりに暑いですね。


__ GRINEditの発表資料: 第39回情報科学若手の会 発表資料「GRINEdit」。 KEMURIの発表資料: 若手の会飛び入りセッション発表資料「今年は変態言語祭り?」(Pythonワンライナー、PythonOnelinerCompressed、Brainf*ckToPythonOneliner、KEMURI)。3日間で合計250枚のスライドを作ってしゃべったんですね…そりゃ喉も枯れるわ。


__ もう1時だ。生産性低いな。今日すること:GRINEditに関するネタがたくさんになりすぎて訳がわからなくなりつつあるので整理する。リリースマネジメント担当者がオンラインになるのを待って最新リリースについて打ち合わせ。

2006年09月17日

日記

PythonからR グラフ描画の問題。 Rpyでうまく描画できない問題は検索しても他の人が見つからなかったので自分の環境だけの問題かと思っていました。他でも起こる問題なのなら上流にシグナルを送信したほうがいいかもしれないですねぇ。

Esoteric programming language - Wikipedia, the free encyclopedia

SOAPに対応すべきかなぁ?

変な言語作りました。 近いうちに解説ページ作ります。

あと、JAPHで何度も使っているソルバーを抽象化したほうがいいかもと思った。

GRINEditが受けたので早急に新しいリリースを作ります。

情報科学若手の会、ダイジェストのダイジェスト。 「貯蓄-投資=輸出-輸入(国際会計恒等式)」「「何々すべき」と計画するのが有害」 「微分方程式もPlaggerでやればいいんじゃね?」 「若手研究者の交流によって視野を広げる(高次元空間非ユークリッド空間に)」 「AJAJAはPerlも呼べる。Perlの膨大なライブラリが使える。」 「次回は情報科学岩手の会」「第39.5回のお題は変態言語」


__ 2泊3日の情報科学若手の会から帰ってきてみると、ほかほかのご飯が僕を待っていました。一人暮らしだけど。

名刺の裏の数独は解いて並べても正しい文字列にならない疑惑が濃厚orz(DOGEZA


__ ナイシトール85を服用して10日でウェスト 4-5cm減 したという日記を読んで、効果の激しさに逆に恐怖を覚えてしまう今日この頃。 原材料を見てみたらマオウ - Wikipediaが入っていたけど、でも麻黄が入っている漢方薬はそんなに珍しくないような気もする。まぁ有名な製薬会社が出している物だから、安全な程度の量にとどめてあるのだろう。たくさん飲んだら痩せるとか思って用法用量を守らなかったりすると危険なんだろうなぁ。


__ とりあえず寝ます。

2006年09月16日

経路探索では中央特快

経路探索では中央特快に乗れと書いてあるのに駅の電光掲示板には各駅停車と書いてあったので悩む。結局来た電車は特快だった。いじめ?中央線と中央本線は違うのか違わないのか。

いま八王子にいます。

いま八王子にいます。お察しください。

日記

ここにあった文章は西尾泰和のブログ: logに移動しました。


__ 7時だ。 旅立つ準備をせねばなるまいて。

発表を、デモをコアに据えて作って、資料とデモのつなぎが高橋メソッド的な形になって、影響されてその前のスライド1枚だったのに20枚の高橋メソッドに変わって、高橋メソッドで初めてデモをした後普通のに戻るわけにも行かなくて続くスライドも次々高橋メソッドに変わっていって…やばい60枚目だ。まだ機能説明だけで普通のスライドが3枚あるし。単純計算でスライド120枚?

わわっ、もういかなky

2006年09月15日

日記

ダメだ猛烈に眠い。

ご飯を食べて9時まで寝て起きて目覚ましをセットして10時まで寝て起きて目覚ましをセットして11時まで寝て11時15分まで寝て、さすがにやばくて飛び起きて椅子の上でねむねむ。13時からミーティング…。うーん。

あっ、そうだ、栄養ドリンクがあったんだ。

すごい、「カフェインが含まれた栄養ドリンクを飲んだ」という意識のせいで一気にエネルギーがわいてきた(気のせい)


__ @早稲田研究開発センター。 ミーティング終了。 さて、ここから一番近い、生産性を発揮できる場所はどこだ? ふむ、秋葉原まで16分か。


__ @秋葉原の喫茶ルノワール。 個々の文章は西尾泰和のブログ: logに移動。


__ 秋葉原から西船橋駅の電車に乗ったら、運良く目の前の人が降りて座れたので ここぞとばかりにBrainf*ck(ぇ

Python onelinerのことをpo、Python oneliner compressedのことをpocと呼ぶことにします。

"bf2po.py"は下のようになります。

bf = file("primes.txt").read()

po = "import sys; from itertools import ifilter, count;"
po += "globals().__setitem__('p', 0)"

for c in bf:
    if c == "+":
        po += " or globals().__setitem__(p, (globals().get(p, 0) + 1) % 256)"
    elif c == "-":
        po += " or globals().__setitem__(p, (globals().get(p, 0) + 255) % 256)"
    elif c == ">":
        po += " or globals().__setitem__('p', p + 1)"
    elif c == "<":
        po += " or globals().__setitem__('p', p - 1)"
    elif c == ".":
        po += " or sys.stdout.write(chr(globals().get(p, 0)))"
    elif c == ",":
        po += " or globals().__setitem__(p, ord(raw_input('>')[0]))"
    elif c == "[":
        po += " or (ifilter(bool, (globals().get(p, 0) == 0"
    elif c == "]":
        po += " for x in count())).next() and 0)"

exec(po)

なんかえらい簡単に動いちゃいましたよ、竹迫さんの100までの素数を列記するプログラムは。テスト用にもっとBrainf*ckのコードを集めてきた方がよさそうだけど、でも間違える余地はあんまり残ってないですよ。まだ新小岩ですよ。 うーん。bf2poc.pyを作るか、それともbf2po.poを作るか…。

exec("import sys; from itertools import ifilter, count; globals().__setitem__('p', 0)"
+ " ".join({
    "+":
        "or globals().__setitem__(p, (globals().get(p, 0) + 1) % 256)",
    "-":
        "or globals().__setitem__(p, (globals().get(p, 0) + 255) % 256)",
    ">":
        "or globals().__setitem__('p', p + 1)",
    "<":
        "or globals().__setitem__('p', p - 1)",
    ".":
        "or sys.stdout.write(chr(globals().get(p, 0)))",
    ",":
        "or globals().__setitem__(p, ord(raw_input('>')[0]))",
    "[":
        "or (ifilter(bool, (globals().get(p, 0) == 0",
    "]":
        "for x in count())).next() and 0)"}[c] for c in file("primes.txt").read())
)

bf2po.poがほぼ完成。unixコマンドっぽくするにはexecの代わりにprintを使って、頭でimport sysしてファイル名をsys.argv[1]にすればいいかと。 あー、でもunixコマンドっぽいというと、ファイルを引数で渡すだけじゃなくて標準入力からも読めた方がいいですね。うーん。Windows使いなので標準入力から読むプログラム作ったことがありません。

もうすぐ終点。次は何をしたら面白いかなぁ。


__ 9時半だけど超眠い。今、会場に一番近い駅に12:30に着く電車を調べたら8時半発だったorz バスもあるらしいけど、もうないんだろうなぁ。ささださんが昨日の時点でバス取れなかったって書いてるし…。 とりあえず眠いんだから寝よう。そして5時ぐらいに起きて頑張ろう。

2006年09月14日

log

基本的にXML-RPCから追加できるすべてのオブジェクトは文字列型のnameというフィールドを持っています。addVertexなどのadd*系メソッドは新しいオブジェクトを作成してそのnameを返します。

鈴木さんの指摘で頂点の一覧を取得する方法がないことに気がついたので getObjectsというメソッドをつけてみました。 getObjects("Vertex")で頂点の一覧が名前とパラメータのマッピングとして取得できます。

それを使ってマインドマップっぽいおもちゃを作ってみました。 詳細は帰ってから書きます(マシン不調のため)

なぜか「 Fault: <Fault 0: 'java.lang.Exception: java.lang.reflect.InvocationTargetException'> 」という例外が2回ほど起きたので原因を究明する。

>>> "保存機能"
SyntaxError: EOL while scanning single-quoted string
>>> "保存機能\"
'\x95\xdb\x91\xb6\x8b@\x94\\'

これってどうやって回避するんでしたっけ。

#
# sample of poor mind-map system
#

# connect to GRINEdit
import xmlrpclib
g = xmlrpclib.Server("http://localhost:8080/RPC2").grinedit


def add(new):
    g.addBoxVertex(new)

def chain(frm, new):
    v2 = g.addBoxVertex(new)
    frm = unicode(frm, "sjis")
    for v in g.getObjects("Vertex").values():
        if v["label"] == frm:
            g.addLinearEdge(v["name"], v2)

while True:
    com = raw_input("command>")
    if com == "a":
        add(raw_input("add>"))
    elif com == "c":
        chain(raw_input("chain-from>"), raw_input("chain-new>"))
    else:
        break

使い勝手は非常に悪いですが、addで頂点を追加し、 chainで新しい頂点を作成して既存の頂点から辺を繋ぎます。 g.getObjectsですべての頂点の情報をマッピングとして取得し、labelが指定された物と一致する頂点を探してそのnameを使って辺を張っています。

>>> import pprint
>>> pprint.pprint(g.getObjects("Vertex"))
{'Vertex0': {'bgcolor': [100, 200, 100],
             'bound': [53, 18],
             'frameColor': [0, 0, 0],
             'label': 'GRINEdit',
             'letterColor': [0, 0, 0],
             'name': 'Vertex0',
             'position': [-0.048417770755790512, 1.1813087342104329],
             'selfLink': False,
             'velocity': [6.9388939039072284e-018, 0.0]},
 'Vertex1': {'bgcolor': [100, 200, 100],
             'bound': [67, 18],
             'frameColor': [0, 0, 0],
             'label': u'\u30de\u30a4\u30f3\u30c9\u30de\u30c3\u30d7',
             'letterColor': [0, 0, 0],
             'name': 'Vertex1',
             'position': [0.49675880770306835, 0.07706468191296624],
             'selfLink': False,
             'velocity': [0.0, 1.3877787807814457e-017]},
(以下略)

ちなみに

    frm = unicode(frm, "sjis")
    for v in g.getObjects("Vertex").values():
        if v["label"] == frm:

の部分は最初1行目を書いていなかったのですが、 そうするとエラーになりました。 Pythonのxmlrpclibで取得した文字列はアスキー文字だけの時はただの文字列、その他の場合はユニコード文字列になるようです。 「'label': 'GRINEdit',」と 「'label': u'\u30de\u30a4\u30f3\u30c9\u30de\u30c3\u30d7',」で、後者だけu'....'というユニコード文字列になっています。 で、3行目「if v["label"] == frm:」の判定で、v["label"]がユニコード文字列の場合にはfrmをユニコード文字列に変換してから比較しようとするのですが、この時frmのエンコーディングが実際にはsjisなのにasciiだと仮定して変換しようとするので「UnicodeDecodeError: 'ascii' codec can't decode byte 0x8d in position 0: ordinal not in range(128)」というエラーが出ます。 それを避けるためにあらかじめエンコーディングを指定して変換してやっているわけです。

日本語環境でのPython (for Python 2.3 or later)の「デフォルトエンコーディング」のところに書いてある方法でデフォルトエンコーディングを変更してやればこの行自体が必要なくなりますが、スクリプトを使う人に「書き換えてください」というのもアレなので…。

こうやって新しいAPIを追加したときに記事に書くと、やっぱりすぐ試してみたい人がいるわけです。次のいつになるかわからないリリースを待ちたくはないでしょう。かといってちょっと機能を追加するたびにリリース作業をするのは大変。リポジトリを公開してそこから最新版を取って貰うのが次善の策。mavenで開発環境が簡単に整えられるようになればいいな。で、subversionで管理して、svkでローカルリポジトリを作り、 普段はそこに対してコミット。 SVKをレポジトリミラーシステムとして使うノウハウ。 開発が一段落付いたらリモートリポジトリと同期を取ってテストをする、と。 mavenでビルドからjarを作るところまで楽に出来るようになったら、それをFTPするところまで自動化してしまうというのも一つの手か…。

日記

【楽天市場】IQ Light:インテリアショップe-goods 。 まるでCGのよう。


__ 「リモートデスクトップ」を「妹デスクトップ」と空耳するんだったら、「リモートリポジトリ」も「妹リポジトリ」と空耳して頂きたい。いろいろな種類の妹がストックされていて、Mavenを使うと必要な妹が自動的にダウンロードされます。

IT-Walker on hatenaを参考にしてmavenのpom.xmlに<addClasspath>true</addClasspath>と書き足したところ、MANIFEST.MFが以下のようになりました。

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: nishio
Build-Jdk: 1.5.0_07
Main-Class: org.nishiohirokazu.grinedit.GRINEdit
Class-Path: commons-logging-1.0.3.jar commons-codec-1.3.jar osgi-3.0.1
 .jar runtime-3.0m8.jar servlet-api-2.2.jar jython-2.1.jar jface-3.0.1
 .jar swt-win32-3.0m8.jar commons-httpclient-2.0.2.jar xmlrpc-2.0.1.jar

問題はこれじゃ実行可能jarファイルと同じフォルダにこれらの依存しているjarがなければならないと言うことです。ルートにずらずらファイルがあるのは目障りなのでlibフォルダの中とかに入っていて欲しいのですが…。

あ、試験管のなかのコード :: Maven2 で JAR の Manifest ファイルを設定する方法をメモによれば <classpathPrefix>lib</classpathPrefix>と指定してやればよいようです。

ついでに必要なjarを全部libフォルダにコピーしてくれればいいのになぁ…と思ったらそういうコマンドがあるそうです。Maven -TECHSCORE-。詳しいことは Maven Dependency Plugin - Maven 2 dependency Pluginに書いてありそう。

maven-dependency-pluginを使うためにはこのプラグインをインストールしないと行けなさそうです。で、ググってみるとoreilly.co.jp -- Online Catalog: Mavenに乗っていると言われました。いやー、その本は家に帰ればあるんだけど今知りたいんだよー。

「mvn plugin:download -DgroupId=org.apache.maven.plugin -DartifactId=maven-dependency-plugin -Dversion=1.0」で出来るはずなのに出来ない。

[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] The plugin 'maven:maven-dependency-plugin' does not exist or no valid ver
sion could be found

だそうな。

Maven Cactus plugin - Installing the Maven Cactus pluginを参考に Index of /maven2/maven/maven-dependency-plugin/1.0から手動でダウンロードしてインストール。 …してみたけど動かないので削除。インストールの仕方が悪いのかな?

      <plugin>
        <groupId>maven</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
	    <version>1.0</version>

Mailing list archivesを参考にして、 setting.xmlに

		<mirror>
			<id>www.ibiblio.org</id>
			<name>ibiblio</name>
			<url>http://www.ibiblio.org/maven2/</url>
			<mirrorOf>central</mirrorOf>
		</mirror>

と書き足したら

Downloading: http://www.ibiblio.org/maven2//maven/maven-dependency-plugin/1.0/ma
ven-dependency-plugin-1.0.pom
160b downloaded
Downloading: http://www.ibiblio.org/maven2//maven/maven-dependency-plugin/1.0/ma
ven-dependency-plugin-1.0.jar
13K downloaded
[INFO] ------------------------------------------------------------------------
[ERROR] FATAL ERROR
[INFO] ------------------------------------------------------------------------
[INFO] null
[INFO] ------------------------------------------------------------------------
[INFO] Trace
java.lang.NullPointerException
        at org.apache.maven.plugin.DefaultPluginManager.addPlugin(DefaultPluginM

と…。一応進展はあったけども解決方法がわからない。 ふぅ。帰ってから本を読んでやることにします。 Re: findbugs for maven2 - NullPointerException


__ 「情報科学若手の会」でググってトップページを見て会場のウェルシティ湯河原のアクセスマップを印刷しました。あれ、招待公演が経済の話だったはずなのに暗号の話になってる…って2005年のじゃんこれ!あぶないあぶない。 これは危険だ。一度行ったことがあるだけに、バスに乗って会場に着いてから会場を間違えたことに気づくところだった。


__ 後ろ髪が伸びてきていてうっとおしい。切ろうかな。 後ろは見えないのでなかなかうまく切れない。 すきばさみできると切られなかった毛がひょろひょろ残ってうっとおしいが、 普通のはさみで変に切ると段差が出来てしまう。下に行くほど短くなるように切ればいいんだろうけどどうすればそうできるかなぁ。


__ 帰ってきて寝て起きたら頭の中のコビトさんが 「ねー、Pythonワンライナーを圧縮・展開するメカニズムを使ったらBrainf*ckを直接Pythonのコードに変換できるんじゃない?」などと言ってきまして、たしかに括弧の扱いだけなんとかすれば可能ですね。 ifilter(bool, (x == 0 or C1 or C2 or C3 ....)).next()でいいのかな。 これは終了時にTrueになってしまうので「(ifilter(bool, (x == 0」と「)).next() and 0)」にすればいいのか…。+は「or globals().__setitem__(p, globals()[p] + 1)」で…。うわー、なんか出来そう。今朝の三時なんだけど、鳥がちゅんちゅん鳴くまでに出来そう。っていうかそんなことしている場合じゃないんだけどな。


__ dependencyプラグインをローカルリポジトリから削除してもう一度mvnを実行してみると、きちんとそれらしき物がダウンロードされてきました。 そこでコマンドラインで「mvn dependency:copy-dependencies」とやってみたらtargetフォルダの中にdependencyフォルダが生成され、中にはjarファイルが入っていました。うまく動いたようです。

でも、swt-win32-3044.dllが必要だといわれてしまいました。swt-win32-3139.dllなら手元にあるのだけど…。

手作業でEclipse downloads - mirror selectionから最新のSWTをダウンロードして配置してやると動きました。うーん。当たり前だけどmavenですべてが解決するわけではないのですね。

Traceback (innermost last):
  File "pythonScripts/init.py", line 30, in ?
ImportError: No module named apache
initMouseMediator.py
initMenu.py
Traceback (innermost last):
  File "pythonScripts/initMenu.py", line 7, in ?
ImportError: No module named eclipse

むむ。Jythonからライブラリをインポートできてないぞ?なぜ?


__ 今日は昼からミーティングがあるからここまでにしておいて寝ることにしよう。 よくよく考えればこんな見栄えのしない作業よりももっと見栄えのする作業に時間を割くべきだった。若手の会での発表資料も出来てないし。明日は今までに作ったデモを全部実行してみて、動かないのがあれば早急に直し、どういう順番で実行するか考えること。


__ SIGGRAPH2005リポート

ABMの基礎となるのはSpatial Algebra、またはSpatial Notationと呼ばれるFetherstone氏が1987が発表したもので、空間の位置を示すのに1x6のベクトル、6x6の変換行列を使うことによってNewton-Euler法の運動方程式、 座標変換、そして複数のDOFを持った関節をあらわすことができます。

おおっ。 そんなものがっ。


__ 404 Blog Not Found:投資するべきではない!=働いてはいけない 。記事を読んで「なるほど」、コメントを読んでまた「なるほど」

PythonワンライナーでBrainf*ckインタプリタ(第二部)

以前のストーリーはこちら: 西尾泰和のブログ: PythonワンライナーでBrainf*ckインタプリタ(第零部)   西尾泰和のブログ: PythonワンライナーでBrainf*ckインタプリタ(第一部)

頻出する文字列をより短い文字列に置き換えることで圧縮するので、ようはngramの計算が必要なんだと思います。 ngramを効率よく計算するにはどうしたらいいんでしょうかね。 とりあえずPythonでSuffixArrayを実装するのが意外と簡単にできたので、それを利用してngramを計算。1000文字ちょいのソースコードに対して、1000~2文字のngram頻度を計算し、その文字列を1文字に置き換えたときに縮む文字数をスコアとして、一番スコアの高い文字列を選択する、というコードが出来ました。

def makeSuffixArray(s):
    result = range(len(s))
    result.sort(lambda x,y: cmp(s[x:], s[y:]))
    return result

def ngram(n, s, sa = None):
    N = len(s)
    if sa == None:
        sa = makeSuffixArray(s)
    prevStr = None
    result = {}
    for i in sa:
        if i + n < N:
            curStr = s[i : i + n + 1]
            if prevStr == curStr:
                result[prevStr] = result.get(prevStr, 1) + 1
            prevStr = curStr
        else:
            prevStr = None
    return result

from time import clock
t = clock()
maxScore = 0
maxStr = None
sa = makeSuffixArray(code)
for n in range(len(code) - 1, 1, -1):
    ng = ngram(n, code, sa)
    for s in ng:
        score = (n - 1) * (ng[s] - 1) - 8
        if score > maxScore:
            maxScore = score
            maxStr = s
print maxScore, maxStr
print clock() - t

大体2秒で結果が出ます。結果はもちろん「globals().__setitem__(」でした。引用符まで含まない方がスコアが高いんですね、ふむふむ。

できました。11秒で1000文字ちょいのワンライナーを578文字に圧縮することができました。

出力はこんな感じ。

'globals().__setitem__(' => 'z' (1401=>815)
')or z"' => 'q' (815=>728)
'(globals().get(p,0)' => 'Z' (728=>677)
'",lambda' => 'Y' (677=>638)
'qc",c+1)q' => 'X' (638=>609)
')for x in count())).next()' => 'W' (609=>587)
')or ifilter(bool,(' => 'V' (587=>573)
'Y:z"c",c+1qp",p' => 'U' (573=>562)
')%256X' => 'T' (562=>555)
'Y:zp,' => 'S' (555=>550)
'import ' => 'R' (550=>547)
'z"c",' => 'Q' (547=>546)
'z"t",' => 'P' (546=>545)
'1)q' => 'O' (545=>542)
置き換えて得になる文字列がありません
542
8.57972759108

コマンドライン引数から実行するBrainf*ckスクリプトを読み込むようにしたら576文字。updateを__setitem__に変えるとなんと547文字まで縮みました。 今回はじゃんけん2.0の教訓を生かして、空白文字やコメントを除去する作業をプログラムに任せたので、比較的見やすい「元のコード」をいじって、より小さくなるコードを探すことが出来るようになりました。

あ、スコアの計算式に間違いがあるせいで縮めた後また伸ばしてました。それを修正すると542文字まで縮みました。上の出力もなおした後のものにしました。

そろそろ飽きてきたのでコードの解説はなし(ぇ)

完成したBrainf*ckワンラインインタプリタはこちら

みどころ。 「>U+O<U-O+SZ+1T-SZ+255T」 これはBrainf*ckの>, <, +, -の定義です。 >U+O <U-O +SZ+1T -SZ+255T。美しい…。

class Compressor:
    def __init__(self, s):
        self.repl = []

        self.target = s
        available = list("|!#$%&()*+,-./:;<=>?@[]^_`{}~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
        import sets
        for c in sets.Set(s):
            if c in available:
                available.remove(c)

        self.available = available


    def step(self):
        N = len(self.target)
        if len(self.available) == 1:
            print "置き換える対象の文字が残っていません"
            return True
        
        c = self.available.pop()

        maxScore = 0
        maxStr = None
        sa = makeSuffixArray(self.target)
        for n in range(N - 1, 1, -1):
            ng = ngram(n, self.target, sa)
            for s in ng:
                score = (n - 1) * (ng[s] - 1) - 2
                if score > maxScore:
                    maxScore = score
                    maxStr = s

        if maxStr == None:
            print "置き換えて得になる文字列がありません"
            return True
            
        self.oldCode = self.getCode()
        self.target = self.target.replace(maxStr, c)
        self.repl.insert(0, c + maxStr)
        print repr(maxStr), "=>", repr(c), "(%d=>%d)" % (len(self.oldCode), len(self.getCode()))


    def getCode(self):
        splitter = self.available[0]
        repl = splitter.join(self.repl)

        return "exec(reduce(lambda x,y:x.replace(y[0],y[1:]),'%s'.split('%s'),'%s'))" % (
                repl, splitter, self.target)



from time import clock
t = clock()

c = Compressor(code)
while True:
    if c.step():
        break
#    exec(c.getCode(), {})
#    print
    
print len(c.getCode())
print clock() - t

PythonでSuffixArray

def makeSuffixArray(s):
    result = range(len(s))
    result.sort(lambda x,y: cmp(s[x:], s[y:]))
    for item in result:
        print item, s[item:]


makeSuffixArray("abracadabra")

10 a 7 abra 0 abracadabra 3 acadabra 5 adabra 8 bra 1 bracadabra 4 cadabra 6 dabra 9 ra 2 racadabra

手抜きをするとこんなに行数が短くて驚きました。 もちろんsortの比較部分で毎回部分文字列を作っているので、これをこのまま巨大な文字列に使っちゃダメですけど、試しに実データで走らせてみると 100文字で1ミリ秒、300文字で8ミリ秒、1000文字で64ミリ秒だったので、僕の今回の目的にはこれで十分でした。 データが10倍になると実行時間が64倍になっているので、1万文字で4秒、10万文字で4分、100万文字で4時間、くらいは最低でもかかると覚悟して使ってください。

PythonワンライナーでBrainf*ckインタプリタ(第零部)

9月11日の日記の中に書いていた内容を切り出して一つのエントリーにしました。以下。


OSASKの川合さんの「BIOSを圧縮してしまってOSASKを入れる」という話を聞いていて全く無関係にワンライナーをさらに圧縮してしまえばさらに短くなると思いついてしまいました。 復元コードが簡単で短くないといけないので長くて頻出する部分文字列を使われていない文字に変換するのが一番ですね。

>>> eval("".join({"^":"lambda ","$":"10"}.get(c,c) for c in"(^x:x+$)($)"))
20

解凍用のプログラムが58文字なのでlambdaが10個あればお得になりますね。 (中略) で、Pythonワンライナーを圧縮するストーリーの続き。解凍用のロジックを導入済みであれば、 長さN出現回数Mの文字列を使われていない1文字に変換することで、 解凍ロジックの長さは 7 + N 文字増え、コードの長さは (N - 1) * M 文字減るので、全体で MN - M - N - 7 文字の削減になります。ささださんの提案された自動ワンライナー化をした場合の嫌なところはよく似たコードだらけになって非効率なところなのですけど、圧縮することを前提にすればそれはそれで悪くないのかも知れませんね。人力で

x.__setitem__("foo", 1) or
x.__setitem__("bar", 2) or
x.__setitem__("baz", 3)
# 77文字

[x.__setitem__(k,v)for (k,v)in[("foo",1),("bar",2),("baz",3)]]and 0
# 67文字

にするよりも

@foo", 1) or @bar", 2) or @baz", 3)
# 35文字 ただし22文字解凍部分で増える

にする方が、同じ「同じ物をまとめる」でもPythonの文法に縛られない分大胆に同じ物をまとめられるので小さくなりそうです。

で、この圧縮解凍を試すためにはターゲットとなるワンライナーが必要なので作りかけた物が以下。まだワンライナーになりきっていないBrainf*ckインタプリタ。一応TAKESAKO @ Yet another Cybozu Labs: Brainf*ckで100までの素数を列挙してみるテストのコードが走ることは確認済みです。 pointerなどの値をglobalsに入れれば参照部分はmem["pointer"]じゃなくてpointerだけになるのだけどそこを手で修正して圧縮するのと機械的に文字列だけ見て圧縮するのとどちらがいいのやら。

# BF Interpreter
import sys
from itertools import count, ifilter

jumpGen = lambda k: lambda :(mem.get(mem["pointer"], 0) == 0) ^ (k == -1) and (mem.__setitem__("t", mem["caret"] + k) or mem.__setitem__("depth", 1) or ifilter(bool, (mem.__setitem__("depth", mem["depth"] + {"]": -1, "[": 1}.get(code[mem["t"]], 0) * k) or mem["depth"] == 0 or mem.__setitem__("t", mem["t"] + k) for x in count())).next() and mem.__setitem__("caret", mem["t"] + 1) or 1) or mem.__setitem__("caret", mem["caret"] + 1)

globals().__setitem__("mem", {"pointer": 0, "caret": 0})
mem.update(
{
    ">": lambda :
        mem.__setitem__("caret", mem["caret"] + 1) or
        mem.__setitem__("pointer", mem["pointer"] + 1),

    "<": lambda :
        mem.__setitem__("caret", mem["caret"] + 1) or
        mem.__setitem__("pointer", mem["pointer"] - 1),

    "+": lambda :
        mem.__setitem__(mem["pointer"], (mem.get(mem["pointer"], 0) + 1) % 256) or
        mem.__setitem__("caret", mem["caret"] + 1),

    "-": lambda :
        mem.__setitem__(mem["pointer"], (mem.get(mem["pointer"], 0) + 255) % 256) or
        mem.__setitem__("caret", mem["caret"] + 1),

    ".": lambda :
        sys.stdout.write(chr(mem.get(mem["pointer"], 0))) or
        mem.__setitem__("caret", mem["caret"] + 1),

    ",": lambda :
        mem.__setitem__(mem["pointer"], ord(raw_input(">")[0]) % 256) or
        mem.__setitem__("caret", mem["caret"] + 1),

    "[": jumpGen(1),
    "]": jumpGen(-1),
}
)
code = file("primes.txt").read() # sys.argv[1]
while mem["caret"] < len(code):
    mem[code[mem["caret"]]]()

今までならこの後jumpGenを2回呼び出すために何らかの辞書に入れてからそれを参照するコードが必要になるのですが、文字列的な圧縮が行われることを前提にすると、この長ったらしい関数定義をそのままコピペで2回使った方が短くなる可能性が高いです。

ただ今の解凍コードでは解凍は一段階だから関数定義自体は圧縮できなくてちょっともったいないかもしれないですね。

最初のコードでは、文字の順に置換をしていったのだけど、そうではなくルール順に置換をするようにすれば、先に置換されるべき物を先に置くだけでよくなりますね。

>>> reduce(lambda x,y:x.replace(*y.split()), "@ ^+^|^ a".split("|"), "@*@")
'a+a*a+a'

PythonワンライナーでBrainf*ckインタプリタ(第一部)

もうちょっとでワンライナーになる状態でほってあった 西尾泰和のブログ: PythonワンライナーでBrainf*ckインタプリタ(第零部)

のコードをワンライナーにしてみます。 今は下のような状況で、orとか挟んで改行をつぶせば一応ワンライナーにはなります。しかし、これに圧縮を掛けて小さくする前に、「圧縮で小さくなることを考慮に入れた上で人力で小さくする」というのをやってみたいです。

import sys
from itertools import count, ifilter

globals().__setitem__("mem", {"pointer": 0, "caret": 0,
"jumpGen": lambda k: lambda :(mem.get(mem["pointer"], 0) == 0) ^ (k == -1) and (mem.__setitem__("t", mem["caret"] + k) or mem.__setitem__("depth", 1) or ifilter(bool, (mem.__setitem__("depth", mem["depth"] + {"]": -1, "[": 1}.get(code[mem["t"]], 0) * k) or mem["depth"] == 0 or mem.__setitem__("t", mem["t"] + k) for x in count())).next() and mem.__setitem__("caret", mem["t"] + 1) or 1) or mem.__setitem__("caret", mem["caret"] + 1)
})
mem.update(
{
    ">": lambda :
        mem.__setitem__("caret", mem["caret"] + 1) or
        mem.__setitem__("pointer", mem["pointer"] + 1),

    "<": lambda :
        mem.__setitem__("caret", mem["caret"] + 1) or
        mem.__setitem__("pointer", mem["pointer"] - 1),

    "+": lambda :
        mem.__setitem__(mem["pointer"], (mem.get(mem["pointer"], 0) + 1) % 256) or
        mem.__setitem__("caret", mem["caret"] + 1),

    "-": lambda :
        mem.__setitem__(mem["pointer"], (mem.get(mem["pointer"], 0) + 255) % 256) or
        mem.__setitem__("caret", mem["caret"] + 1),

    ".": lambda :
        sys.stdout.write(chr(mem.get(mem["pointer"], 0))) or
        mem.__setitem__("caret", mem["caret"] + 1),

    ",": lambda :
        mem.__setitem__(mem["pointer"], ord(raw_input(">")[0]) % 256) or
        mem.__setitem__("caret", mem["caret"] + 1),

    "[": mem["jumpGen"](1),
    "]": mem["jumpGen"](-1),
}
)
globals().__setitem__("code", file("primes.txt").read()) # sys.argv[1]

from itertools import count, ifilter

ifilter(bool, (
    mem["caret"] == len(code) or
    (mem[code[mem["caret"]]]() and None)
    for x in count())).next()

現状ではmemというハッシュとglobals()というハッシュが存在しますが、全部globals()にしてしまっていいと思いました。圧縮を掛ければ「globals()」が1文字に変わりますし。mem["pointer"]と参照しているところもpointerで済みます。ついでですから、これも1文字の変数名にしましょう。 pointerがp, caretがc, codeがs, jumpGenがj,あとジャンプの中でdとkを使っています。

import sys
from itertools import count, ifilter

globals().__setitem__("c", 0)
globals().__setitem__("p", 0)

globals().__setitem__(
"j", lambda k: lambda :(globals().get(p, 0) == 0) ^ (k == -1) and (globals().__setitem__("t", c + k) or globals().__setitem__("d", 1) or ifilter(bool, (globals().__setitem__("d", d + {"]": -1, "[": 1}.get(code[t], 0) * k) or d == 0 or globals().__setitem__("t", t + k) for x in count())).next() and globals().__setitem__("c", t + 1) or 1) or globals().__setitem__("c", c + 1)
)
globals().update(
{
    ">": lambda :
        globals().__setitem__("c", c + 1) or
        globals().__setitem__("p", p + 1),

    "<": lambda :
        globals().__setitem__("c", c + 1) or
        globals().__setitem__("p", p - 1),

    "+": lambda :
        globals().__setitem__(p, (globals().get(p, 0) + 1) % 256) or
        globals().__setitem__("c", c + 1),

    "-": lambda :
        globals().__setitem__(p, (globals().get(p, 0) + 255) % 256) or
        globals().__setitem__("c", c + 1),
        
    ".": lambda :
        sys.stdout.write(chr(globals().get(p, 0))) or
        globals().__setitem__("c", c + 1),
        
    ",": lambda :
        globals().__setitem__(p, ord(raw_input(">")[0]) % 256) or
        globals().__setitem__("c", c + 1),
        
    "[": j(1),
    "]": j(-1),
}
)
globals().__setitem__("code", file("primes.txt").read()) # sys.argv[1]

ifilter(bool, (
    c == len(code) or
    (globals()[code[c]]() and None)
    for x in count())).next()

memをすべて取り除きました。さて。「globals().__setitem__(」がほぼ間違いなく1文字に圧縮されるであろうことを考えると、globals().updateはsetitemにしたほうがいいのかもしれません。でも微妙。

とりあえず以前作った(まだ公開していない)onelinerizeライブラリで構文上不必要な改行やコメントを取り除いてみると1167文字。

globals().clear()
code = """
import sys;from itertools import count, ifilter;[
globals().__setitem__("c", 0) or
globals().__setitem__("p", 0) or
(以下略)
"""

from onelinerize import Tree2TinyCode

code = Tree2TinyCode().feedStr(code)
print len(code)
exec(code)

これを圧縮したときにどれくらいの長さになるのかは、圧縮するアルゴリズムを作って実際に試してみるのが一番です。で、それは次回に回したいと思います(ぇ)

2006年09月13日

GRINEdit よくある失敗

  • AddVertexではなくてaddVertex。基本的にメソッド(関数)の名前は頭が小文字、"CircleVertex"などのクラス(物の種類)の名前は頭が大文字
  • addVertexなどの1番目の引数は文字列。addVertex(CircleVertex, {})ではなくaddVertex("CircleVertex", {})
  • うっかり頂点を投げたら遠くに飛んでいってしまった→壁制約(PL_Wall)をaddLawすればよい。

GRINEditのGoogleGroupを作りました

ご質問、ご要望などはお気がねなくどうぞ。

Google Groups GRINEdit_jaに参加
メール アドレス:
groups.google.co.jpアーカイブを参照_LINK

日記

夜中の4時まで太ももを出して作業をしていたら冷えてしまったらしく、のどがいがいがです。 もう秋なんですねぇ。


__ YouTube - 日本の形:交際(ラーメンズ)(1/3) YouTube - 日本の形:交際(ラーメンズ)(2/3) YouTube - 日本の形:交際(ラーメンズ)(3/3) なんだか今までのとはちょっと雰囲気が違いますね。


__ なんか本当に寒い。もう暖房が必要なの? 寒波?雨のせい? ジャージを着ているのに膝が寒い。膝掛けが欲しい。

夏の間しまっていた寝袋を出してきて下半身を寝袋に入れて作業。暖かいけど、足の間に棒が入るタイプの椅子なので両足を寝袋に入れると座りづらい。片足を寝袋から出す。下にチャックのあるタイプでよかった。

冬もこれならこの穴から電気毛布を入れればよさそう。


__ うーん。気分が悪い。


__ ぁぅぁぅ。24時を回ったぐらいから体調が戻ってきて、喜んで作業をすればいい物をやらなくていいことをやってもう27時半…。何やってるんだ自分…。することはいっぱいあるのに…。

今日は木曜日、明日の金曜日にはとある所でミーティングがあり、土曜日から若手の会かな。場所どことか全然調べてないし、発表資料も出来てない。たぶんデモの時間を多めに取ることになるだろうなぁ。

maven

手元にはjarファイルがあるけどもリポジトリにはなかったり、リポジトリにあるのを落としてきたのにコンパイルが通らなかったり、色々大変。

プロジェクトに必要なJarを勝手にダウンロードしてくれる、というと便利そうだけども、どのJarが必要かは自分でXMLを書かないと行けないのです。

Maven Repository: Search/Browse/Explore を使ってアーティファクトIDとかを調べて記述。

Maven入門 (2) Maven -TECHSCORE-。リモートリポジトリにないときは自分でどこかから入手してローカルリポジトリに入れなければ行けません。

きちんとやったつもりなのに「パッケージ org.apache.xmlrpc は存在しません。」と怒られてこまりはてました。 リモートリポジトリに入っているJarをEclipseでビルドパスに指定してやるとEclipseでビルドできるのに、

依存性の設定のスコープの値をcompileにするとうまく行きました。

ビルドには成功して、実行可能なJarも出来たのですけど、実行するとNoClassDefFoundError。 これってあれですよねきっと。実行時に外部のJarを参照できていないという罠。 でももう28時半なので寝ます。

試験管のなかのコード :: Maven2 で JAR の Manifest ファイルを設定する方法をメモ

オフラインミーティングのログ

未踏ユースのブースト会議で発表したり、GRINEditを使ってみたいという人のマシンにソースコードを入れて開発環境を整えたりしてきました。

開発環境を整えるための手順

  • まずEclipseに空のプロジェクトを作成
  • srcフォルダにソースコードをコピー
    • ファイル名「cvs」で検索してcvs情報のフォルダを消した
    • ほんというとリポジトリからチェックアウトしてもらえるようにしておくべき。
  • Jarファイルをクラスパスに追加
    • SWT関係
      • org.eclipse.swt_3.1.0
      • org.eclipse.jface_3.1.1
      • org.eclipse.swt.win32.win32.x86_3.1.2
      • org.eclipse.core.runtime_3.1.2
    • XML-RPC関係
      • xmlrpc-2.0.jar
      • commons-codec-1.3.jar
    • Jython関係
      • jython.jar
    • 動的にロードされるものがあるので コンパイルエラーが出なくても追加する必要があることに注意。
  • プロジェクトのルートディレクトリにconfig.pyとswt*.dllとpythonScriptフォルダをコピー
  • config.pyに書かれているpythonScriptsフォルダの位置を修正する

備考。 Macで動かすには「org.eclipse.swt.win32.win32.x86_3.1.2」のようなライブラリが必要そう。 JythonがインストールされていないとJythonコンソールを出すメニューはエラーを出す。 Jythonコンソールを使わない多数派のユーザにJythonのインストールを強要することはしたくないので、これはinit.pyでXML-RPCをON/OFFしているような方法でメニューをON/OFFしてしまえばいいのではないだろうか。

  • グラフの頂点以外に画面に表示したい物がある
    • それも頂点として実装する
    • 反発や引力などの物理演算はみんなターゲットを指定できるようになっている
    • 実はaddVertexメソッドは"vertex"という名前に関連づけられたHashtableに 指定されたオブジェクトを作って入れるだけ。
    • addObjectメソッドで"vertex"以外の物に追加すればいい
    • 移動は物理演算
  • マウスの操作のカスタマイズはどこでやる?
    • →MouseOperationでやる
    • TODO:これもプラグインで追加できるようにする
      • addMouseOperationで追加、setMouseOperation("name", "LEFT")で左マウスボタンに割り当てとかかな?
      • MouseOperationプラグインのサンプルを作る
        • ドラッグドロップでドロップされた付近の頂点に対して何かする
          • 頂点を頂点にドラッグドロップすると辺が出来るとか
          • 入れ子になるとか
  • 既存ソフトウェアの一部として使うとき、 すでにそのソフトウェアにある頂点クラスにはRenderableVertexを継承させられないケースがある
    • 描画と無関係の「位置」や「速度」などを持ったクラスがある(MassPoint)ので それを既存の頂点クラスに持たせる。
  • GRINEditのjarを作っておくべき。
  • キャンバスのAWT化
    • アプレットにする際に楽
  • XML-RPCで全部の頂点の情報をまとめて取得するメソッドを作る
  • getVertexでvertexの情報を取得する側のサンプルコードがない。書くべし。
  • 非矩形選択ができるといいなぁ
    • しかもそれを畳んだり出来るといいなぁ
  • 辺のIDのプレフィクスがvertexになっているのを修正する
  • ピン留めされていることをはっきり表示する 清木さんのアイデア
    • もちろんピン留めされたときにピンの絵を出す頂点をプラグインとして作れば実現できるが、そんな些細なことでいちいちJavaで開発しないと行けないのは重荷
  • リファクタリングするべき?
    • 辺と頂点の選択方法(なんでMediatorに実装されてるんだ!)
    • 選択時の表示の変化(でもどう変えるのがいいのだろう?)
      • 現状のSelectionの仕様
        • Selection.setで既存の選択範囲に含まれる頂点のselectedをfalseにし 新しい選択頂点をselected=trueにする
    • キャンバスサイズが決めうちなのはよくない
      • config.pyで設定?init.pyで設定?
      • メインのGUI自体をプラグイン化?
  • 必要のないプラグインの中までサーチしないようにすべき?
    • →現状ではpluginsフォルダの中にあるjarファイルから探している
    • →「必要ある/ない」を切り替えるためには、設定をするためのファイルを用意するか、 設定用のスクリプトに書き足すなどの作業が必要になる
    • →HashtableでJarのロケーションとON/OFFの対応を持たせておいて 個々のプラグインフォルダのconfig.pyでそのON/OFFを切り替えられるようにしておく?

2006年09月12日

日記

奥村先生のカラー二次元コードの問題@結城浩の日記

僕の回答も同じ「正しくない」ですが、理由はちょっと違います。

理由1:モノクロの二次元コードは2のn乗の情報が入り、それをカラーにしたものは1677万のn乗の情報が入るので、838万のn乗倍である。

理由0(奥村先生の問題を最初に見たときに思った方): 出力の分解能と入力の分解能は違う。


__ TAKESAKO @ Yet another Cybozu Labs: Development Environment Conference 報告

そういう意味で開発環境だったのですか!

「CVS は小学生まで」 orz。

「svnは小学生まで。svkを使おう!」 o...rz

ショートカット専用キーボードってのは 長野テクトロン お気に入りキーボード - ShopU - livedoor デパート ですかね。 上から順番に「Ctrl + Alt + A」「Ctrl + Alt + B」…というキーだそうな。

で僕はアンテナ低いので気がついたときにはすでに「4分で予約埋まったプギャー」と騒ぎになっている時だったわけですが。


__ 若手の会のデモセッションにBrainf*ckネタが2つもあるのは、 僕のセッションで自己紹介代わりに「Pythonワンライナーで作ったBrainf*ck」をやれという天の声でしょうか(ぇー


__ 今日のおもしろおかしい。 「sed awk して船 山に登る」

log

GRINEditは現在CVSとAntで管理されているが、SubversionとMavenに移行したい。 とりあえずMavenの最新版をダウンロード。Maven 2.0のインストールを参考に、一応HelloWorldと表示するJarが出来ました。

フォルダの構造とかがだいぶ違うんですねぇ。

2006年09月11日

日記

傘連判状(からかされんぱんじょう)をコミュニケーションに応用するというのは面白いなぁ。

あー。WISSの話を聞いて、GRINEditはWISSで発表するといいのかもなぁと思ったのだけど、発表の締め切りが9月3日まででもう終わってしまってました。残念。

ActionScriptでDIコンテナかぁ、ActionScriptもどんどん書きやすくなっていきますね。

上下ジーパン。後で見る。

goo注目ワード ピックアップ・・・上下ジーパン男 (goo注目ワード) - goo ニュース

音楽にぴったり合っている動画にあわせてナレーションSUGEEE。

胃が苦しいなぁ。昨日はちょっと飲み過ぎたかも。

netPlantはいいなぁ。mixiのコミュニティとはてなブックマークとグラフのびよびよが合体したようなものなのかな。

「実際に動くところを見たい方はいますか?」って質問はずるいなぁ。今度使おう(ぇ)

10月上旬にベータ版。

ActionScriptでグラフのびよびよが出来るといいなぁ。将来的にはFLASHでもGRINEditが動くといいなぁ。FLASHはきれいなのが簡単(?)に出来ていいなぁ。

ディスプレイロボット。 目玉いいなー、目玉。 SourceForge.net: Open Computer Vision Libraryで顔認識とかも出来るそうです。


__ ふぅ。お酒を飲み過ぎたので、例年よりなんだか疲れました。 そして昨日は取る物もとりあえず駆けつけたので、帰ってくるといろいろな物がいろいろな状態に。豚肉はぎりぎりで冷蔵庫にほりこんだんだけど、キヌサヤとご飯とお茶は常温で24時間放置されました。お茶は捨てて、キヌサヤは問題なさそうで、ご飯は…僕の鼻が確かなら大丈夫。


__ 寝て起きたら25時半。もうちょっと「朝型」と言えるような時間まで寝ることをもくろんでカーテンを開けたまま寝たのになかなかうまく行きませんね。

ここに書いてあった文章は 西尾泰和のブログ: PythonワンライナーでBrainf*ckインタプリタ(第零部)に移動しました。

2006年09月10日

日記

ソフトバンク ビジネス+IT:【ストリーミング】 Lightweight Language Ring(LLRing)[2/3:対戦「じゃんけん2.0」]/ビジネスインパクト。 自分の声はやっぱり変な声に聞こえる。 前半はやっぱりダレ気味だなぁ。「まぁ」が多すぎる。 やはり無限リストの遅延評価は説明文がなさ過ぎて理解しづらい。 try...except文の実装でリターンコードを使っていると勘違いしている人が多かったのはなぜかと思っていたのだけど、エラー出力をパースしてエラーの内容を特定しています、という説明の所は会場の爆笑がかぶって聞き取りにくい状況になっていたようですな。 ワンライナーの後のデメリットの説明もスライドの文章読んだりしてまだるっこしい。 「結論『から』言います」じゃないな、最後なんだから。

やっぱりもっと早い時点にネタを仕込むべきなんだろうなぁ。 竹迫さんの発表なんか開始10秒で最初の笑いが現れるもんなぁ。

あれ?関数言語セッションや最後の短い発表の動画はないの?


__ 火炎放射器 : Gizmodo Japan(ギズモード・ジャパン)。火炎放射器の自作。 ガソリンは引火性があるからこういう遊びに使うのは危険ですよ。 タンクに残ったガソリン気体に引火・爆発して失明したり指を失ったりしてから悔やんでも遅いです。


__ えー、もう15時?! 8時に起きて二度寝して12時に起きて13時にご飯を炊き始めたのでまだ朝ご飯を食べていません。もっとリズム感をもって生活しないと行けないなぁ。

キヌサヤはこれにしました→美味しい「キヌサヤエンドウの卵とじ」のレシピ。ちりめんじゃこの代わりにこの前作ったベーコンビッツを入れたんですけど、意外とおいしかったです。

でもキヌサヤはまだたくさん余っています。どうしようかなぁ。


__ ガッ、未踏ユースのブースト会議のことをきれいさっぱり忘れていた!今から行きます!


__ すっかり忘れていたせいで発表準備が出来ていなかったのでLLGongの資料をやたら長い前座に使う手に出てみました。自己紹介用に2-16(西尾)とか竹内6-61和田とかブラウザで開いておいたのに使うの忘れました。まぁ、流れに入れにくかったからいいか。

せっかくLLGongの発表資料に手を加えたのに手を加える前のバージョンでプレゼンしてしまったのと、デモをしようと思ったらこの前手を加えたところのせいでXML-RPCが動かなくなっていたのが要対処。デモは最新版をEclipseから起動するのではなく、ちゃんと動くバージョンをJarから起動するようにした方がいいですね。

こけた原因。 XML-RPCのライブラリがリフレクションを使っているので、パラメータはHashtable以外の物では受けられない。以前Mapで受けようとしてうまく行かなくて知っていたはずなのに、すっかり忘れていた。Objectで受けてリフレクションで変換する様にしたせいでXML-RPCがこけてしまうのだ。

とりあえず大急ぎで修正してデモは無事出来ました。そうだ、覚えているうちに書いておくと、プロシンの飲み会でうまく動かなかったのは動かなかったのが正しい挙動で、ラベルのない頂点を含むグラフの全頂点に対してgetLabelを呼んだから、そりゃそんなメソッドはないって言われて当然。エラーメッセージがわかりにくいのがよくないね。「~ってメソッドはない」だけではなく「~ってクラスには~ってメソッドはない」と出すようにすべき。

入れ子頂点はもっとじっくり腰を据えて対処すべき問題だということが判明。レンダリングエンジン自体をXML-RPCで差し替えられるようにする方針で。「高速なレンダリングエンジン」「入れ子頂点をレンダリングできるレンダリングエンジン」「3Dのレンダリングエンジン」なんてのを切り替えられるようにしよう。

2006年09月09日

Position Paper (ja)

プログラミングシンポジウムで配布したポジションペーパーを公開します。

可遊化とは(その2)

西尾泰和のブログ: 可遊化とはの続き。

前回は、可遊化を「楽しい/楽しくない」という尺度で切りましたが、最近はもうちょっと違う切り口で切った方がいいのではないかと感じています。

可遊化されていないシステムは、左脳の言語的思考だけを使って考えるが、可遊化されたシステムは、右脳・左脳の両方を使って全体的に考える。 言語的な思考が必須であるようなシステムでは、左脳の能力しか生かせない。しかし、非言語的な思考が可能なシステムでは、言語的ではない、意識上に顕在していない思考も反映することが出来るのではないだろうか? 言語的でない思考も動員できるのではないか?

そんなことを考えています。

生物学的には、女性の方が男性より「左脳と右脳を繋ぐ脳梁」が太い、というのは事実な訳です。そして、科学的には検証されていませんが「女のカン」という物の存在は広く認められている物と思います。 「カン」とはなんでしょうか?それはある情報からある結論を導き出し、しかし「なぜそういう結論を導き出したか」は言語的に説明できない、というタイプの推論ではないでしょうか?

科学は、言葉で表現できることを要求します。 「カンで決めた」というと、それは根拠のない馬鹿げたことのように考えられます。 しかし、カンで決めた結果が、ランダムに決めた結果よりもよい結果をもたらすのであれば、結論を導き出した理由を言葉で説明できないからといって捨ててしまうには惜しいのではないでしょうか?

人間の知的活動のうち、言語的に説明できる部分はごく一部です。 男性でもそうです。あなたは自転車に乗るときにどう重心移動するかを言葉だけで説明できますか?酔っぱらって記憶がないのに家まで帰ってきたことはありませんか?自分は家の鍵を閉めたかどうか覚えていないのに、確かめてみるときちんと閉めていたりしませんか?そういう「非言語的思考」のリソースを、単に言語で記述して他人に伝えることが出来ないという理由で捨ててしまうのはとてももったいないことなのではないでしょうか?

その非言語的思考を拾い上げようとするのが、可遊化の目的なのかも知れません。

日記

ハチミツとクローバーを読んだら、自転車で北海道まで行きたくなってしまいました(ぇ)

顔写真は魚眼レンズっぽいというおびなた君の指摘をうけて、そういえばプロが顔写真を撮るときと素人が顔写真を撮るときで大きく違うのはカメラと顔との距離だな、と思いました。レンズの位置が近いせいで歪みが出たのかも知れませんねぇ。 あとは大至急写真を送ってくれと言われてあわてて取ったので表情が硬いところも変かも知れません。っていうか自分の写真を見てどこが変なんだろうと悩んでいるところを後ろから見た人が「誰か知らない男性の写真を眺めて悩んでる?!」と思ったそうな。そんな趣味じゃないですから。

今日はもう18時半。時間を無駄にしてしまった。昨日はなぜか非慣性座標系で見かけの力が発生する話を、高校生相手にするハメになってしまった。謎。IRCを起動すると仕事にならないなぁ。

あー。2次元ベクトルを90度回転させようとして間違えている高校生に、じっくり考えさせようと思って「図を描いてみろ」って言ったのに、なぜかグラム・シュミットの正規直交化法を使って解決している…。

わかってきた。社長と僕とで高校生の教育方針が違うんだな。

僕としては、2次元での回転を理解してから3次元に進んで欲しいし、回転座標系で発生する見かけの力の話も、加速度のある電車の中発生する見かけの力を理解してから進んで欲しいんだけど「やる気のある若いやつ」相手には社長がやっているようなジャンプアップの方が効率がいいのかも知れないなぁ…。

教育は難しい。


__ 「仕事が進まないときはメタ仕事」

こういう何となくだれて仕事が手に付かないときには、仕事の整理をしたり机の整理をしたりしよう。手帳が付箋だらけになっているし。

付箋から。最近新しくした携帯に英単語ゲームが入っていて、電車の待ち時間とか楽しく遊ばせてもらっています。でも和英に比べて英和の難易度が高く感じるのは気のせいでしょうか。和英は初日にクリアできたのに英和は未だにクリアできません。taciturn:無口な。revel:お祭り騒ぎ。 actuary:保険数理士。satchel:カバン。 sprain:ねんざ。 callus:たこ(指に出来るほう)。binge:どんちゃんさわぎ。 tithe:十分の一。cater:迎合する。speck:少量。初めて目にする単語がわんさか。

albatrossの訳を選択肢から選ぶんだけど、正解の選択肢は信天翁。ちょ。


__ ダメだ。 ダメだ。 ダメだ。 ちっとも手に付かない。 そこでアルコールを投下。

頭が回らないときにはカフェインを投下するが、 頭が回るにもかかわらず空回りして手が動かないときはアルコール。 頭が回ってある作業Xをしようとすると「いやYが先でしょ」となってしまう。 実際にはXはYが終わってからやると楽で、YはXが終わってからやると楽、というデッドロックになっているのだ。 とりあえずアルコールを入れて、そしてどれから先にやるのが効率いとかそんなのはうっちゃって目の前の作業をするのだ!

あー、でももうちょっとゆっくり飲むべきだったのかも。 500mlで7%だから35mlか。35mlのアルコールを摂取したら、 大脳皮質だけではなく運動野も冒されたと見えて、 タイプミスの頻度が上がって生産性が落ちてしまいました。 もうちょっとほどほどに飲むべき。 っていうか回るのはやいな、なんで? あ、胃が空だからか。 なるほど。


__ 酔っぱらいがまた雑文を垂れ流していますよ。笑ってやってください→西尾泰和のブログ: 可遊化とは(その2)

酔っぱらい物書き(ドランクライター?)にとって、ATOKはいいよー。TABで補完が効くからー。


__ うー。 高校生に虚数単位のiのi乗がわかったんですが、あってますか、って聞かれて、説明を聞いてみたらあってるんだから怖いよねぇ。とりあえずオイラーの公式をe^(x * i) = cos(x) + i * sin(x)とか言っているのでe^zの場合を考えてもらうことにしよう。


__ 生姜の甘酢漬けがおいしい。勝手にキュウリやニンジンを追加したキムチと、そろそろ乳酸菌発酵が始まったのか酸っぱくなってきた野沢菜と、生姜の甘酢漬けをつまみながら。


__ うわーん。 高校生と抽象アスペクトとか抽象ポイントカットとか話してるよぅ。ついてけないよぅ。

ボース・アインシュタイン凝縮とか言ってるよう。こわいよう。うえーん。

2006年09月08日

My "Just Another * Hacker," stash

Details are in 西尾泰和の日記(2006-02-02) (written in Japanese but majority is Python)

Detail is in 西尾泰和のブログ: Just Another Python Hacker, その2

Detail is in 西尾泰和のブログ: Just Another Python Hacker, その3

Profile

Here is Japanese version. To contact me, send e-mail to nishio dot hirokazu at gmail dot com.

NISHIO Hirokazu(Hirokazu is given name) was born in 1981. He received B.Sc. degree from Nara Institute of Science and Technology (NAIST) in 2004. He received Ph.D. (science) degree from NAIST in 2006.[PDF] He wan been a Research Fellow of Japan Society for the Promotion of Science from 2005. His research interests include Visualization of Large-scale data obtained from biological experiments. He is a member of Information Processing Society of Japan and Japan Society of Artificial Intelligence.

He is Just Another Python Hacker, and his latest paper is Spherical SOM and Arrangement of Neurons Using Helix on Sphere[PDF]

History

  • 1981-07-23 I was born.
  • 1994 I entered Nada junior high school --- 1997 I graduated it.
  • 1997 I entered Nada high school --- 2000 I graduated it.
  • 2000-4 I entered Kyoto University (Dept. of Infomatics and Computer Science) --- 2003-3 I skipped grade.
  • 2003-4 I entered Nara Institute of Science and Technology(NAIST), Graduate School of Information Science Master's cource --- 2004-3 I graduated it in minimum term.
  • 2004-4 I entered NAIST Doctor's course --- 2006-3 I graduated it in minimum term.
  • 2002-11/2003-03 Information-Technoogy Promotion Agency, Japan(IPA) Exploratory Software Project (Exploratory Youth)
  • 2004-05/2005-02 NAIST teaching assistant
  • 2004-08 Ministry of Education, Culture, Sports, Science and Technology (MEXT) IT cultivation of human resources project, IT School 2004 tutor
  • 2005-04/2006-03 Japan Society for the Promotion of Science (JSPS) Research Fellow (DC2)
  • 2005-08 MEXT IT School 2005 tutor
  • 2006-04 to now JSPS Research Fellow (PD)
  • 2006-05 to now Department of Computational Biology, Graduate School of Frontier Sciences, University of Tokyo
  • 2006-08 MEXT ICTSchool 2006 tutor

English papers

  • GIW2002 "Genome Visualization by Isometric Projection Focused on Replication Origins and Termini, and Genome Instability" Nishio, H., Wada, K., Wada, Y., Fukushima, A., Ikemura, T., Mori, H., Oshima, T., Kanaya, S. Genome Visualization by Isometric Projection Focused on Replication Origins and Termini, and Genome Instability. Genome Informatics 13: 449-450 (2002)
  • WSOM2003 "Visualization of Gene Classification Based on Expression Profile Using BL-SOM" Nishio, H., Amin, M., Sato, T., Wada, K., Wada, Y., Minato, K., Kobayashi, K., Ogasawara, N., and Kanaya, S. (2003) Visualization of gene classification based on expression profile using BL-SOM., Proc. of WSOM03, 101-106.
  • RECOMB2004 "Suitability of Spherical SOM for Gene Expression Analysis" Nishio, H., Wada, K., Wada, Y., Amin, M., Kanaya, S. Suitability of Spherical SOM for Gene Expression Analysis. Proc. of RECOMB2004
  • SCI2004 "Gene classification Based on Expression Profile using BL-SOM: Suitability assessment of multivariate gene expression data to Spherical and Plain SOM by N-measure"Nishio, H., Altaf-Ul-Amin, M., Nakamura, Y., Abe, T., Kinouchi, M., Ikemura, T., Kobayashi, K., Ogasawara, N., Kanaya, S. Gene classification Based on Expression Profile using BL-SOM: Suitability assessment of multivariate gene expression data to Spherical and Plain SOM by N-measure. SCI2004
  • WSOM2005 "Spherical SOM with arbitrary number of neurons and measure of suitability"
  • IPSJ TOM "Spherical SOM and arrangement of neurons using helix on sphere" IPSJ Transaction on Mathematical Modeling and Its Application, Vol.47 No.SIG1 (TOM 14) pp. 56-60
  • Cybozu Lab, Inc. Software Engineer.

Award

日記

もう3時半だ。大至急昔論文に貼った写真を探してくれと言われて、外付けHDDを全部引っかき回していたのだけど、結局目的の物は見つけられず。おかしいなぁ、消すはずはないと思うんだがなぁ。少なくとも自分の写真と自分の略歴の文章は再利用が出来るから捨てるはずはないと思うんだがなぁ。

仕方がないので自分の写真はもう一度撮影し、略歴は書き直しました。

英文で書くために自分の英語のプロフィールのページを探してみました。もしかして最新ってNISHIO Hirokazuこれ?博士取得するまえのまま止まってるじゃん!早急に英語版のプロフィールを作らないと。あ、でも3時半か…今からラボに行くべきか行かざるべきか。ちなみに昨日一昨日は行っていません(ぇー)

基本的にほとんどの作業が家で出来るからラボに行く必要性が薄いんだよなぁ…。どちらかというと家の方がプログラミングしやすい環境だし。


__ 自分の英文を読み直していると…実験によって得られたデータは「data obtained by experiments」じゃないだろうと小一時間問い詰めたくなります。experimentsがobtainしたのかと。Google先生に聞いてみると「そこはfromかthroughだな」と返事が返ってきます。ガッ。っていうかexperimentがそもそも複数形になってない!

そんなことよりもっと重大な問題を発見しました。2003年に修士を取ったと書いてあるけど実際は2004年。学歴詐称だ!


__ さて、いちおう英語版のProfileが出来ましたが…僕ってこんな顔だったかなぁ?なんか違和感が…。鏡で見るのと左右逆だということを差し引いても違和感が残ります。照明のせいかな?

あんまり違和感がひどいので左右反転した写真に差し替えました。比較してみたい人は/files/kao_small.jpgと/files/kao_small_r.jpgを比べてみてください。

後は英語版の「活動ダイジェスト」が欲しいところだけど、それはすなわち日本語の記事を英語に翻訳してからリンクを貼るということなので工数が多い。


__ 劇的ビフォ(ry

そんなもの作ってる場合じゃなくて自分。

女性読者の皆様、今ならお一人様一枚までなんと破格の100%オフで画像修正を承ります!(笑)


__ 今週末の新しくチャレンジする素材はキヌサヤ。 最近下ごしらえが重要だというのがわかってきた気がします。 先にまとめて処理しておけば楽ちん。今日買ってきたキュウリは板ずりしてキムチの容器へ。ニンジンもレンジで加熱して一部キムチの容器へ、一部胃の中へ、残りは冷凍。カボチャは堅いから日持ちすると思って放置しすぎて、先週買ったカボチャは種の所からカビが生えてしまったので、今回のは早速レンジでチン。種を取って袋に入れて、袋の中でつぶしてみました。これなら胞子が巻き込まれにくいから食中毒のリスクも少なめのはず。冷めたら冷凍庫に入れます。


__ プロシンで教えて貰った ̄torito_ ドデカパズル ノナ(NONA)。 探索で解かずに数学で解けと挑発されているので考えてみたのだけど結構難しいです。帰りの電車で考えたのを忘れないように貼っておきます。

>>> def calcHash(self):
	p1 = self.index(1)
	p2 = self.index(2)
	p3 = self.index(3)
	p4 = self.index(4)
	v2 = (p2 + 5 - p1) % 5 - 1
	v3 = (p3 + 5 - p1) % 5 - 1
	v4 = (p4 + 5 - p1) % 5 - 1
	p = v2 >> 1 & 1
	f2 = (v2 & 1) ^ p
	v3 ^= 3 * p
	v4 ^= 3 * p
	return (f2 * 4 + v3) * 4 + v4

>>> def perm(aList):
	if len(aList) == 1:
		yield aList[:]
	else:
		for item in aList:
			restList = aList[:]
			restList.remove(item)
			for rest in perm(restList):
				yield [item] + rest

>>> d = {}
>>> for i in perm([1, 2, 3, 4, 5]):
	d[calcHash(i)] = i

	
>>> d
{6: [5, 4, 3, 2, 1], 7: [5, 4, 1, 2, 3], 9: [5, 3, 4, 2, 1], 11: [5, 3, 4, 1, 2], 13: [5, 4, 2, 1, 3], 14: [5, 4, 3, 1, 2], 18: [5, 4, 2, 3, 1], 19: [5, 4, 1, 3, 2], 24: [5, 3, 2, 4, 1], 27: [5, 2, 3, 4, 1], 28: [5, 3, 1, 4, 2], 30: [5, 2, 4, 3, 1]}
>>> len(d)
12

calcHashで求めたハッシュ値の同一性を同値関係として[1, 2, 3, 4, 5]の並び方全通りを同値類に分けると、12個の同値類に分かれます。あとはこの同値類から1個ずつ選んで12面体の表面に並べることを考えよう。


__ リリースは政治パフォーマンスなんだよ。なるほど。自分が矛先になると素直に受け入れられないかも知れないけど、Ruby使いですらない第三者の視点から見ていると、やっぱりやると言ったことはやるべきなんだろうなと思えてきます。僕も気をつけよう。

log

  • 入れ子頂点の中の頂点への辺が外の頂点に上書きされないようにするには。
  • 現状ではすべての辺を描いてからすべての頂点を描いているので上書きされてしまう。
  • すべての頂点を描画した後で輪郭から輪郭までの辺を描画すれば解決する。
    • この方法の問題点は、計算量の増加。輪郭と辺の交点計算をすべての頂点が毎フレーム行うようになるとパフォーマンスが悪化するのではないかと心配。
    • しかも通常の(入れ子のない)グラフの可視化では現状のレンダリング方法で問題がない。
    • もしこの重い方の計算方法を入れるのなら、切り替えられるようにすべき。
  • 今は辺の方向ベクトルを渡すと輪郭と辺の交点の中心からの距離を返すメソッドがある、がNarVisualizerの頂点を考えるとこれでは弱い。
    • 輪郭上の接続すべきポイントを返すメソッドであるべき。
    • 曲線・折れ線の辺を考えた場合、これでもまだ弱く、「辺の出る方向」も返すべき。
    • 折れ線辺の例として縦と横の線だけで2回までの折り返しで接続する辺のサンプルがあった方がいいのかもね。

2006年09月07日

日記

盗難されて行方不明になっていたムンクの「叫び」が発見されたそうですねー。めでたい。

盗難されて?行方不明になっている僕の自転車はやっぱり行方不明…。買うか…。


__ 自転車買ってきました。人間用の空冷ファンまで買ってしまいました。

あー。実家から送られてきた巨大な箱もまだあけてないのに…。部屋を片付けて物を置くところを作らないと…いろんなところが散らかっている…。

箱にほりこんだりして片付けてしまうのは簡単だけど、後でどこに何があるかわかるように片付けるのは難しい。


__ IronPython1.0が出たようですねぇ。


__ 携帯にカメラが付いたのでがらくた箱なんてのを作ってみたけど「写真を撮って、メールに添付して、説明文をつけて、送って、(ここで携帯が勝手にカメラモードを終了して、もう一度立ち上げて)」を繰り返すのは想像以上に面倒だった。カメラはワンタッチで取れて、説明は音声でつけられて、ブログへの投稿も自動で出来るといいのにな。それをやるなら携帯じゃなくてUSBカメラか。それなら音声入力の所はキーボード入力で妥協してもいい。今もカメラと対象の距離がばらつくことで明るすぎたり暗すぎたりしているけど、USBカメラと照明を据え付けておけばいいだけだしなぁ。例えばEnterを押すと撮影して、画面にプレビューを出して、それを見てOKならコメントを描いて投稿ボタンを押すと、自動的に画像のアップロードと投稿をしてくれるというプログラムを作ればいいんだな。Pythonで。Javaを使わないでGUIを作るのの練習に作ってみるのも悪くないかも。


__ 教授/半教授/四半教授とか(ぇ)>わたなべさん


__ しまった、中途半端に片付けたから寝る場所がない。

log

  • CommonGatewayが組み込み名前空間に入っていない件
    • XML-RPCでアクセスする際にはserver.grineditがCommonGatewayを指している
      • grinedit.addVertex(...)
    • Jythonスクリプトからのアクセスの際にもgrinedit.addVertexでアクセスできるようにした。
  • Jythonから叩くとPyDictionaryでXML-RPCから叩くとHashtableである件
    • PyDictionaryのコンストラクタにHashtableを渡すことが出来るが…
      • HashtableをPyDictionaryに変換してから処理するってのは美しくない気がする
    • 引数がHashtableのメソッドとPyDictionaryのメソッドの両方があるのはコードクローン
    • HashtableをPyDictionaryに変換してPyDictionaryに統一するのが一番いいのかなぁ。
    • Jython.jarとの結合が密になりすぎるが…。
    • PyDictionaryにtoHashtableがあれば済む話なのになぁ。
    • Jython.jarとの結合が密になりすぎるのを避けたければPyDictionaryの側をHashtableに変換すべきなのかも知れないが…
    • PyDictionaryに統一したら動かなくなった。
         File "(略)", line 41, in load
      java.lang.ClassCastException: java.lang.String
      	at org.python.core.PyList.(PyList.java)
      	at org.python.core.PyDictionary.keys(PyDictionary.java)
      	
    • キーがjava.lang.StringであるようなHashtableをコンストラクタに渡して作ったPyDictionaryのkeysメソッドを呼ぶとClassCastExceptionが再現される。Jythonのバグだろうか?どちらにせよ、このバグを取ったとしてもJythonから渡されたPyDictionaryのキーはStringじゃなくてPyStringになっているからJavaから使い勝手が悪い。
      < if(_params.has_key(new PyString("name"))){
      <   name = _params.__getitem__(new PyString("name")).toString();
      < }
      > if(_params.containsKey("name")){
      >   name = _params.get("name").toString();
      > }
      
    • うむ、やっぱりPyDictionaryが来たときにはHashtableに変換する方針で。
  • それは済んで、入れ子の頂点がうまく動いたときにわかるように中に入る頂点から他の頂点に辺を繋いでみる
    • 動かない。原因は頂点の名前空間にjava.lang.Stringの文字列をキーにして入っている頂点オブジェクトを取得するのにPyStringのオブジェクトをキーにして探していた為にnullが返っていること。問題点はわかったが、その問題を解決するために一番酔い解決方法は何か。
    • ふむふむ。StringのtoStringはreturn this;だからオーバーヘッドはほとんどないな。修正完了。
    • これで赤がりんご、黄色がバナナにつながればOK。
    • ただここまで書いて想像が付いたのだけど、今は頂点を先に描画してそれから頂点を描画しているので内側の頂点へつながる辺は外側の頂点の輪郭で途切れてしまうだろう。難しい問題だ。描画コードはパフォーマンスに直結するだけに、パフォーマンスを落とさずに一般化することを考えないと行けない。
    • 頭が回らないのでもう寝よう。5時だし。

2006年09月06日

日記

Python Developers Campに参加するかどうか悩みどころです。9月29日スタートでなければためらいなく参加しているんですけどね…。うーん。


__ 今気がついたのだけど、駐輪場に駐めていた自転車がなくなっていました。盗難?(汗)


__ Telebody::Falcon

The Python contestant made a herculean effort to use Python, known for being sensitive to indentation, in a one-liner. However, in the end this was only possible by running the program in a child process, since try..except is over one line itself. The conclusion of that programmer was an emphatic, “[In Python,] One-liners are bad!”

herculeanって何かと思ったらヘラクレスなのね。日本語に訳せば「めっちゃ頑張ってた」という感じか。そんなに頑張ったつもりはないのだけど、西尾泰和のブログ: Pythonでワンライナーを作成する際のノウハウ集の英語版を作った方がいいのかも知れませんねぇ。そう考えると、プロフィールとダイジェストも英語版を作るべきかも。


__ NHK 世界遺産の旅 【トルコ ヒエラポリスとパムッカレ】。白い!PAMUKKALE。これ温泉なのか!もう保護されて入れなくなってしまったそうだけど…。


__ Amazon.co.jp: セックスのあと男の子の汗はハチミツのにおいがする: 本: おかざき 真里

な、なんだってー!ΩΩΩ


__ GUIにもパイプが欲しい。「このウィンドウの情報をこれに送れ」って感じの。


__ 兄弟-姉妹型人間学ってのがよくわからなかったので検索してみたのだけど、確かに血液型と性格よりは、例えば「姉がいるかどうか」と性格の方が相関がありそう。


__ どうすればPlaggerでダイエットが出来るか本気で考えかけた。とりあえずPhidgetをベルトにつけてみるとか。


__ Google Analyticsをつけてみました。このブログのindex.htmlと各エントリーアーカイブにトラッカーを埋め込んであります。2,3日経ったらどんな感じかレポートしてみます。

東京へ帰る新幹線にて

頂点に力をかけるのが出来るようになりました。 新しいMouseOperationを追加する予定だったのですが、 ほとんどMO_MoveVertexと同じだと気がついたのでMO_MoveVertexに追加してみました。 頂点をドラッグすると移動して、普通に離すとその場に固定されます。 そしてShiftを押しながら離すと、固定されません。 新しく追加した機能は「Ctrlを押しながら離したら直前の移動量分の力がかかり続ける」と「Ctrl+Shiftを押しながら離せば力が消える」というものです。(大きなネットワークを投げたときに自然じゃないので修正される予定)

入れ子に出来る頂点作成ログ

  • BoxVertex.javaをコピーしてNestableVertex.javaを作る。
  • しばらく眺める
  • コピーじゃなくて継承でよかったと気づく
  • NestableVertexにBoxVertexを継承させて、フィールドを削ってみる
  • privateなフィールドをprotectedに変更
  • コンストラクタの中身をsuper()にする
  • renderメソッドだけ残してすべてのメソッドを消す。priveteなメソッドの一部をprotectedに変更
  • Jythonコンソールから頂点を作成してみて、この時点で動くことを確認しておく。
    • (修正済み)CommonGatewayインスタンスは組み込み名前空間に入っていない?「cg = med.getCommonGateway()」などとやって取得しないと行けないのは面倒。
    • (修正済み)Jythonから「cg.addVertex("NestableVertex", {})」とやると「TypeError: addVertex(): 2nd arg can't be coerced to java.util.Hashtable」になる。「import java」して「cg.addVertex("NestableVertex", java.util.Hashtable())」ならOK。これも面倒。
  • いちいちJythonコンソールを起動してこういうことをするのは(コンソールの起動待ちが特に)面倒なのでnestableVertexTest.pyを作成。実行時に起動するように設定。
    • 今のテスト用のスクリプトがちょっと微妙だからPyUnitを使えるか試してみよう
  • 起動すると頂点が出ることを確認。
  • NestableVertexにList childrenというフィールドを追加。
  • Listか。
  • 「public void addChild(NestableVertex v)」を作る。テスト用スクリプトからそれを呼ぶ。
  • 子のサイズを見て自分のサイズを適切に調整。
  • 自分をレンダリングする際に子もレンダリング、ただし同じ位置に。
  • さてと、もう新横浜だ。後は子供が自分で自分を描画しないようにする必要があり、親に対して適切な位置にとどまる必要がある。これは制約で実装する。NestableVertex自体が制約で、コンストラクタで自分自身を制約リストに登録するとか。あ、ダメだ、Javaは多重継承が出来ないから頂点が制約にはなれないや。
  • 子供が自分自身を描画せず、親が全部描画するようにした。しかし子の位置を動かして親の付近に固定すると、おそらくそれに反発して親の頂点が動いてしまうだろう。今は位置をいじらずに外見だけ親の中に入れている。親と子は反発して欲しくないが、子から他の頂点への辺は子の中心から出て欲しいし、その辺ももちろん引力を保って欲しいので「中に入れられた頂点は物理演算の対象から外す」という方法では解決できない。さてどうするか。
  • 子も親からの反発力で動くようにした上で、重心の位置と傾きを保持する制約で形を保たせる。これが物理的には一番正しそう。これならば子供につながっている辺が及ぼす引力で親も動くし、子と親の間にどんな力が働いているかわからなくても作用反作用の法則で全部打ち消されてくれるはず。

GRINEdit用語集

MouseOperation:各種マウス操作を受け持つクラス、またはそのオブジェクト。MouseOperationクラスの子クラスである。

todo

  • (修正済み)Jythonから「cg.addVertex("NestableVertex", {})」とやるとエラーになる件。addVertexなどのメソッドがHashtableではなくObjectを受け取り、リフレクションするとか。(これではXML-RPCでリフレクションでメソッドを探すときに失敗するのでダメ)
    • JavaがHaskellみたいに複数の型をまとめて新しい型に出来ればいいのにねー。
    • Hashtableを受け取るメソッドと、PyDictを受け取るメソッドの二つを作ればリフレクションするまでもないか。
  • PyUnitを試す
    • 選択部分のバネの自然長を縮めるコンソールでの作業が出来るかチェック。いくつかのデモの要素をテストできるようにしておく。

2006年09月05日

位置メール

未来館の脇から [GoogleMap]

いまいち精度が高くないね…。

GPSで取った現在位置からGoogleマップへのリンクを作成する

SA702iを使ってGPSで取得した現在位置をメールでMTに投稿した時に、デフォルトのままではPCユーザが見ることが出来ないDocomoサーバ内の地図のURLが表示されるだけで面白くないので、適当な地図サイトへのリンクにすることを考えてみました。

携帯のGPSで取った緯度経度でそのままマピオンの地図を表示するとずれています。測地系 - Wikipediaで紹介されている国土地理院による日本陸上用の変換CGIを使って、携帯GPSからの情報を世界測地系として日本測地系に変換した上でマピオンに渡すとそれっぽい位置になりました。しかし変換は面倒なので世界測地系を採用している地図を探してみると…。Googleマップでいいようですね。

Pythonで試し書き。

data = "http://docomo.ne.jp/cp/map.cgi?lat=%2B33.35.26.977&lon=%2B130.25.15.976&geo=wgs84&x-acc=1"
PAT = "(http://docomo.ne.jp/cp/map.cgi\?lat=%2B(\d+).(\d+).(\d+.\d+)&lon=%2B(\d+).(\d+).(\d+.\d+)&geo=wgs84&x-acc=\d+)"
TEMPLATE = "http://maps.google.co.jp/?t=k&ll=%f,%f"
def docomo2google(m):
  (a, lat1, lat2, lat3, lon1, lon2, lon3) = m.groups()
  lat = (float(lat3) / 60 + float(lat2)) / 60 + float(lat1)
  lon = (float(lon3) / 60 + float(lon2)) / 60 + float(lon1)
  return TEMPLATE % (lat, lon)
  
re.subn(PAT, docomo2google, data)

こんな感じですね。 あとはこれをPerlで書き直してMovableTypeのフィルタにすればOK、と。 問題はそんなことより、僕の携帯のGPSナビゲーションがなぜか「接続できません」というエラーで使えないことなのですけどねー。近いうちにドコモショップに聞きに行かないと…。

sub docomo2google{
    my($lat1, $lat2, $lat3, $lon1, $lon2, $lon3) = @_;
    my $result = "";

    my $lat = ($lat3 / 60.0 + $lat2) / 60.0 + $lat1;
    my $lon = ($lon3 / 60.0 + $lon2) / 60.0 + $lon1;
    return "&lt;a href='http://maps.google.co.jp/?t=k&amp;ll=$lat,$lon'>[GoogleMap]&lt;/a>";
}

# 変換部分(自作フィルタの中)
$text=~s|http://docomo\.ne\.jp/cp/map\.cgi\?lat=%2B(\d+)\.(\d+)\.(\d+\.\d+)&lon=%2B(\d+)\.(\d+)\.(\d+\.\d+)&geo=wgs84&x-acc=\d+|&docomo2google($1,$2,$3,$4,$5,$6)|ieg;

出来ました。

日記

ノートパソコン用スタンド【これはいるか】。使ってみた人の体験談を探してみて「キーボードとモニターは上に上がったけどマウスは下だからかえって疲れる」という意見を見つけて「なるほど」と思ったものの、僕トラックポインタ使いだからマウスないじゃん


__ ここにあった記事は西尾泰和のブログ: GPSで取った現在位置からGoogleマップへのリンクを作成するに移動しました。


__ 余った配付資料と名刺を回収してくるのを忘れてしまいました。まぁいいか…。名刺の方は名前の前に「工学博士」と書いていないアンド自己紹介で「東京大学で学振特別研究員(PD)をやっている西尾です」とは言いにくくて「東京大学の西尾です」と言ってしまうので博士の学生だと勘違いされてしまうということがわかりましたし。あれ、僕って工学博士だっけ理学博士だっけ(ぉぃぉぃ)


__ 世界に通用するソフトウェアであるかどうかはどういう客観的な指標を用いれば判定できるのでしょうか。世界に通用するソフトウェアを作るにはいったい何を頑張ればいいのでしょうか。書類書きで困ってます。


__ FAQ/Living - 大学生にもなって今さら聞けないコト。まとめwiki(参考になる: +3)

GRINEditのアイデアをつれづれと

GRINEditでFreeMindみたいにInsやEnterでさくさく頂点追加出来るようにするためには、キーイベントのリスナもプラグインから登録できないといけない。 プラグインから登録されるリスナはフラットではなく、チェインであるべきかな。あと実行時に動的に変化できるべき。特定のモードを選んでいるときだけアクティブなリスナ。リスナの中で条件分岐で反応するかどうかを決める設計の方がいいのかも知れない。

頂点にフォーカスがあたっているときのキー入力イベントのデフォルトは頂点のラベル編集?

TouchGraphの三角形の辺は実装が簡単だし、今直線の辺だけで選択肢がないのでちょうどいいからとさくっと実装してみました。

新しい辺クラスTriangleEdgeを実装する際に自分がやったことの記録。 LinearEdgeをコピーする→renderメソッドの中身を望みの物に変更 →必要なフィールドを作成、不要なフィールドを削除 →setXXXを作る(引数はObject1個) →getParamsを直す

本当は既存のをコピーするんじゃなくて、新しい頂点や辺を作る時用のテンプレートとかを用意した方がいいのかも知れないけど、現状では頂点にしても辺にしても十分小さいクラスなのでさほど実害がない。まぁ、でも用意するのも別に難しくはないし、つくっといた方がいいかもなー。

で、TouchGraphはネット接続を使いそうだったので、代わりにPythonの構文木をXML-RPCで可視化するスクリプトを作成。構文木を調べるコードが21行で、それを可視化するコードが25行。簡単。ただ、構文木は子の順番に意味があるのに、何も考えずに可視化するとシャッフルされてしまうから、ツリーであることが明確なデータに関してはツリーを可視化する用の物理法則とか、初期配置とかにした方がいいのかも。

それから帰りの電車で川北さんと話が盛り上がっていくつかアイデアを貰いました。

まずsodaplay。このクリーチャーデータの再生自体はプラグインで「周期的に伸縮する辺」を入れればいいだけなので簡単なのだけど、soda constructorのほうを実現するためには、位相と振幅を指定するためのサイドパネルが必要。当然GRINEditに決めうちでサイドパネルを入れても意味がないので、プラグインからサイドパネルを出す必要があります。一応、プラグインはただのJarだからウィンドウを開いたりも出来るとは思うのですが、クラスローダが本体とは異なるからswt.jarやswt.dllなんかが別途必要になってしまうかも知れないですね。試してみる必要があるでしょう。

でもそれが実現できれば「拡張性の高いアプリです」という主張の説得力が増しますね。

次に、頂点の入れ子。ある頂点をつかんで別の頂点の中に入れることが出来る機能。ネットワーク状の情報を整理するときにはこの機能があると便利そうです。ただ、現状では頂点をつかんで他の頂点に近づけると反発力で逃げてしまいますね。「物を入れられる頂点(以下、箱)」を作るだけで解決できるとうれしいのですけど、それがうまく行かないと「箱」と「箱にはいることの出来る頂点」の両方を作らないと行けないのかも。もちろん実際に実装するなら「箱は箱に入ることが出来る」という設計にすると思いますけど、どちらにせよ今の頂点クラスを使えなくなるわけです。うーん。よく考える必要がありそう。別に今の頂点クラスは単にデフォルトのグラフ可視化用に使われているだけであって、入れ子に出来るNestableVertexクラスを作ってそれで構成されたネットワークを作ること自体は別に設計上の問題にはならないのかな…。

部分的に重力をかけると面白い、というアイデアもありました。これはGUIにないだけでXML-RPCやJythonではすでに出来ます。GUIでやるときの問題点は「どちら方向にどの程度の力をかけるか」をどうやって指定するかですね。あー、「範囲を選択してメニューから選ぶ」というのを考えていたけども、そうじゃなくて新しいマウスアクションを追加して「頂点をつかんでぽいっとやると、投げた方向に飛んでいく」でいいのかも。それがいいな。

あとこれは僕のアイデアですが、音声認識して形態素解析して頻出するキーワードを頂点として追加するプログラムがあると面白いですね。時間的な近接関係で辺が張られ、頻出キーワードはタグクラウドみたいに大きく表示されるといい。可視化部分は現状のシステムで問題なく実現できるはずなので、後は音声認識をして形態素解析をしてそれをXML-RPCで投げるプログラムがあればいいわけです。


__ 今、一つ前のアイデアメモで「XML-RPCハンドラもプラグインから追加」と書いてあるのを見て「GUIもプラグインから作成したらなんでもかんでもプラグインだなぁ」とか思ったんですが、もう一歩踏み込んで本当に何でもかんでもプラグインにしてしまえばクラスローダの違いによる問題は起きないのではないかと気づきました。つまりデフォルトのGUI自体がプラグインという設計。本体は本当に最小限にしてしまうということ。

プログラミングシンポジウム日記最終日

増井先生の「全世界プログラミング」で紹介されていたPhidgets Inc. :: Unique and Easy to Use USB Interfacesはとても面白そう。

NecoLogger は存在自体は知っていましたが、開いているウィンドウのテキスト文字列も取得できるというのは知りませんでした。僕もログを取ってみようかな。

名刺の裏の数独は和田先生にHaskellでさくっと解かれてしまいました。光栄です(笑)

EdamameというFlashでFlashを作ることの出来るツールの紹介があったのですが、どこで使えるのかがわかりませんでした。

AjaxでAjaxを作るAroe。Aroe - Cho Shinya's page。コード中のタグはオブジェクトの生成。サーバサイドのPerlとクライアントサイドのJavaScriptの両方を生成してくれます。

2006年09月03日

学会行きの電車の中でつれづれと

学会行きの電車の中でつれづれと考える。

早めにNarVisualizerをプラグインで実現できるか試そう。 プラグインで実現できるようにプラグインシステムを改良しよう。

GRINEditの現状のプラグインシステムはpluginsフォルダ内のjarファイルの 中から実行時にクラスをロードできるというだけだが、 ユーザにとって使いやすいプラグインシステムはEclipseみたいに 「ダウンロードして解凍して適当なところにコピーすれば それだけでメニューが追加されたり機能が増えたりする」 というものだ。 pluginsフォルダの中にjar以外の物を入れると、 現状では無視される(これを利用してドキュメントを書くことも出来る)が、 pythonスクリプトが入っていれば起動時に実行することにするといいかも。 そのスクリプトで自分自身の機能をON/OFFするメニューを追加させたり、 翻訳データファイルに追加をさせたりする。

XML-RPCハンドラもプラグインから追加したい。 handlerId = grinedit.loadHandler("org.…")とかやってロードさせて、 grinedit.apply(handlerId, "methodName", params)とやって呼び出す。

ドラッグドロップのハンドラもプラグインから追加させる。 例えば画像ファイルをドラッグドロップするとそれのサムネイルが入った頂点が出来、 ダブルクリックすると開く、とか。 PDFファイルをドラッグドロップするとPDFのアイコンとタイトルの入った頂点が出来、 ダブルクリックすると開くとか。

いまダブルクリックはスルーしているけど、最寄りの頂点のdoubleClickedメソッドを呼び出す、とかでいいかも。

操作マニュアルの自動生成。 今はMouseOperationインスタンスは メニューに表示する文字列だけを持っているが、 メタキーによる修飾をサポートしたので機能がメニューに書ききれなくなった。 機能説明の文字列も持たせよう。

頂点のサイズ変更とか、頂点の中の文字列も動的に書き換えたいですね。 プラグインで出来るかな、それ。

グラフをネットワーク越しに共有して複数人で同時に編集できるようにするには…。 サーバで物理演算をやって、クライアントはその結果を受け取って表示するだけにするか。もちろんクライアントが頂点を追加したり移動したりした場合にはその情報がサーバに送られる、と。JythonやXML-RPCではない操作も全部CommonGatewayを通すことにして、そこでサーバと通信するのが全部まとまっていて楽そうだけど、パフォーマンスはどんな感じになるんだろうか。

GRINEditにコマンドライン引数でPythonスクリプトを渡した場合に、 init.pyなどの実行が済んで初期化が完了した後、 現在start.pyが実行されているタイミングで そのスクリプトが実行されるようにしよう。 そうするとGRINEdit test.pyでテストが起動され、 GRINEdit narVisualizer.pyでNarVisualizerモードで起動し、 何も指定しなければプレーンなGRINEditが起動する、なんてことができる。

タブレットでスケッチっぽく頂点や辺の追加がしたい。

プログラミングシンポジウム日記2日目

眠いけどあと1時間で自分が座長のセッションが始まるので寝るわけに行かない。

今回は未成年の参加者が2人もいたので平均年齢が下がったらしい。しかも片方は女の子。

TouchGraph。PHS接続では大変なので帰ってから試そう。

やっぱりグラフの要約機能や動的に開いたり閉じたりする機能は需要があるようだ。

あと30分なのでとりあえず会場に移動するか…。

2006年09月02日

プログラミングシンポジウム日記

帰ってからちず窓βで地図を貼れるようにしよう。

Ruby/TkORCA。 VNCみたいにネットワーク越しでGUIが使えるけども、 GUIの操作を監視できる仕組み、らしいです。 クライアントはVNCビューワーでOKで、 Flashみたいにブラウザの中に埋め込んで使うことも出来るそうな。 2000~3000行くらいのTkで書かれたGUIアプリを、 もらって1時間でネットワーク対応に出来るそうです。ふむふむ。 「ローカルで作ったGUIアプリが 簡単にネットワーク対応に出来る」というところが重要なようです。

プログラミングシンポジウム日記

携帯からの投稿は結構遅れるようなので時系列に並べ直してみました。


2006-09-02 10:09:12 いまここ。

[GoogleMap]

URLがつくだけ?


2006-09-02 12:57 いまここ(博多)

[GoogleMap]


2006-09-02 13:33 いまここ(べふぅー)


2006-09-02 13:42:28 プログラミングシンポジウム日記

今、福岡の別府駅にいますが、会場は大分の別府でした。orz。

別府駅に来て「送迎バスは別府駅西口って書いてあるけど西口がないなぁ」と思ったら…。

もう一度博多駅まで戻って新幹線で小倉に行って乗り換えか…ここから二時間半。迷っても大丈夫なようにと早めに出て、送迎バスの40分前に別府駅についたのに、まさかゴールを間違えているとは。


2006-09-02 14:27 わざとじゃないのに

博多駅とか別府駅とかからの投稿が伏線になってる件について。

「事実は小説よりも奇妙だ、なぜなら小説にはリアリティーが必要だが現実には不要だからだ」とか言ってた人がいたけどなにこのオチ。信じらんない。誰がこの脚本書いたの?

座長をやるセッションが今日じゃなくて本当によかった。


16:33 これが正解

フロッピー型のブラシ

フロッピー型のブラシ

日記

眠れないときは起きるに限ります。


__ 書き忘れてましたが、携帯を新しくしました。カメラがつきました。GPSもつきました。というわけでMovable Typeで、携帯電話から写真画像付きでエントリを投稿(moblog)-studio mdを見ながら設定をしてみます。

「Your account and/or XMLRPC API is not available.」と言われるのでどうした物かとGoogle先生に相談したら XML-RPCからアクセスできるようにするために、携帯用のアカウントでパスワードの設定をしないといけない、と教えて貰いました。HELLO WORLD.(ほぼ日刊 野狐禅): MT32でmoblogする際の注意点

お、出来た出来た。

がらくたの写真を撮って素材や予想される用途と一緒に投稿していけば、必要になったときにすぐに探せるかな、なんてことを考えています。

ISBNから登録できない本(雑誌や論文)を書籍管理プログラムに登録するのも、やっぱり写真を撮ってコメントを自分で書くのが一番の近道かと。


__ なんか、眠れないからといって特に理由もなくウェブ巡回をするのはよくない習慣のような気がしてきました。


__ WindowsMediaPlayerの視覚エフェクトを作るためのウィザードがSDKの中に入っていたけども、ExpressEditionなのが行けないのか、どうすればVC++からそのウィザードを選べるようになるのかがわからない。

log

GRINEditテストすべきこと getParamsで取得できる値を改めてsetParamして きちんとうまく行くこと。

テスト用のスクリプトを書いた。

UtilXMLRPCクラスの中に入っていた、型変換に関するメソッドを UtilCastクラスに移動。 以降UtilXMLRPCがSWTやAWTに依存しないように気をつける。 UtilCastはSWTやAWTに依存しているが、 アプレット版を作る際にはUtilCastからSWTへの依存を取り除いたバージョンを作って それを使えばいいだろう、おそらく。

XML-RPC経由でインスタンシエイトするインターフェイスで 引数のないコンストラクタを呼び出してからmodParamsで 各種パラメータをセットしているので、 引数のないコンストラクタが定義されていないと InstantiationExceptionが起きる。

デモ用のスクリプトが、デモ前にデモがちゃんと動くかどうかのテストにも使えた。

2006年09月01日

Just Another Ruby/Python Hacker,

実行すると

Just Another Ruby/Python Hacker,

と表示されます。cygwinで確認しました。

なお、このRubyワンライナーを作るにあたってRubyのある風景 - rrencodeのてくにかるいしゅーが非常に参考になりました。というかRubyは詳しくないので自力では無理でした。

なお「どのへんがPythonなんだ」と思う方は実行されたコマンドの最後と下の「このRubyスクリプトを作るのに使ったPythonスクリプト」の最初の方を読むとわかるかも知れません。


__ 使う記号の種類を限定してさらにひどいものにしてみました。「<<」を文字列の結合とシフト演算の両方に使ったり、「?)-?(」(イコール1)を多用するようにしたり、という嫌らしいことをしてあります。?(や?)のせいで、ただでさえ括弧を頼りにして読むことが難しいのに、括弧を必要以上につけてあるのでさらに読みづらくなっています。でもなんかきれい。

ruby -e "_=%?%?<<?!+?!+?!;$><<_%((((?)-?())+(?%+(?%<<?)-?())))<<_%((?%+(?)+?+)))
<<_%(((?%+(?+<<?(-?)))<<?)-?())<<_%((?%+(?-+(?-<<?(-?)))))<<_%((?%+(?%<<?)-?()))
<<_%(((?%+(?%<<?(-?)))<<?)-?())<<_%((?%-(?--?()))<<_%(?-)<<_%((?%+(?(+(?-<<?(-?)
))))<<_%((?%-(?--?()))<<_%((?%-(?(-?%)))<<_%((((?)-?())+(?%+(?%<<?)-?())))<<_%((
?%+(?%+?()))<<_%((?(+(?++(?-<<?(-?)))))<<_%(((?%+(?%<<?(-?)))<<?)-?())<<_%(((?%+
(?+<<?(-?)))<<?)-?())<<_%((?%-(?--?()))<<_%((?(-((?)-?())))<<_%((?%<<?)-?())<<_%
((?%+(?(<<?)-?()))<<_%((?%+(?%+?))))<<_%(((?%+(?+<<?(-?)))<<?)-?())<<_%((?%-(?--
?()))<<_%((?++(?-<<?(-?))))<<_%(((?%+(?%<<?(-?)))<<?)-?())<<_%((?%+(?%<<?)-?()))
<<_%(((?%+(?+<<?(-?)))<<?)-?())<<_%((?%+(?-+(?-<<?(-?)))))<<_%((?%+(?++(?+<<?(-?
)))))<<_%((?%+(?%+?()))<<_%((?%-(?--?()))<<_%((?)<<?)-?())<<_%((?%+(?(<<?)-?()))
<<_%(((?)+(?--?%))<<?)-?())<<_%((?%+(?)+?+)))<<_%((((?)-?())+(((?)-?())+?-)))<<_
%((?(<<?)-?())<<_%((?%+(?)+?+)))<<_%(((?%+(?+<<?(-?)))<<?)-?())<<_%((?%+(?-+(?-<
<?(-?)))))<<_%((?%+(?%<<?)-?()))<<_%(((?%+(?%<<?(-?)))<<?)-?())<<_%((?%-(?--?())
)<<_%(((?%-((?)-?()))<<?)-?())<<_%((?%+(?(+(?(<<?(-?)))))<<_%((?%+(?(+(?-<<?(-?)
))))<<_%((?(+(?-+(?-<<?(-?)))))<<_%((?%+(?++(?+<<?(-?)))))<<_%((?%+(?%+?()))<<_%
((((?)-?())+?+))<<_%((?(-((?)-?())))<<_%((?%-(?(-?%)))" | sh

シンプルに「Just Another Ruby Hacker,」と表示するスクリプトは下のようになります。

ruby -e "_=%?%?<<?!+?!+?!;$><<_%((?%<<?)-?())<<_%((?%+(?(<<?)-?()))<<_%((?%+(?%+
?))))<<_%(((?%+(?+<<?(-?)))<<?)-?())<<_%((?%-(?--?()))<<_%((?++(?-<<?(-?))))<<_%
(((?%+(?%<<?(-?)))<<?)-?())<<_%((?%+(?%<<?)-?()))<<_%(((?%+(?+<<?(-?)))<<?)-?())
<<_%((?%+(?-+(?-<<?(-?)))))<<_%((?%+(?++(?+<<?(-?)))))<<_%((?%+(?%+?()))<<_%((?%
-(?--?()))<<_%((?)<<?)-?())<<_%((?%+(?(<<?)-?()))<<_%(((?)+(?--?%))<<?)-?())<<_%
((?%+(?)+?+)))<<_%((?%-(?--?()))<<_%(((?%-((?)-?()))<<?)-?())<<_%((?%+(?(+(?(<<?
(-?)))))<<_%((?%+(?(+(?-<<?(-?)))))<<_%((?(+(?-+(?-<<?(-?)))))<<_%((?%+(?++(?+<<
?(-?)))))<<_%((?%+(?%+?()))<<_%((((?)-?())+?+))"

これらのコードを出力したPythonスクリプトは下記。

import sets

targetStr = "python -c \"print 'Just Another Ruby/Python Hacker,'\""
#targetStr = "Just Another Ruby Hacker,"

target = sets.Set([ord(x) for x in targetStr])

#mark = "!\"#$%&'()*+,-./:;<=>@[\\]^_`{|}~"
mark = "()+-%"
caches = []
levels = {}
cache = {}

for m in mark:
    v = ord(m)
    cache[v] = "?" + m
    levels[v] = 0
    if v in target:
        target.remove(v)

cache[1] = "((?)-?())"
levels[1] = 0

caches.append(cache)

for level in range(1, 10):
    print level
    cache = {}

    i = level - 1
    for x in caches[i]:
        # *2
        v = x * 2
        if not(levels.has_key(v)):
            cache[v] = "(" + caches[i][x] + "<<?)-?()"
            levels[v] = level
        # /2
        v = x / 2
        if not(levels.has_key(v)):
            cache[v] = "(" + caches[i][x] + "<<?(-?))"
            levels[v] = level

    for i in range(level):
        j = level - i - 1
        for x in caches[i]:
            for y in caches[j]:
                # add
                v = x + y
                if not(levels.has_key(v)):
                    cache[v] = "(" + caches[i][x] + "+" + caches[j][y] + ")"
                    levels[v] = level
                # sub
                v = x - y
                if not(levels.has_key(v)):
                    cache[v] = "(" + caches[i][x] + "-" + caches[j][y] + ")"
                    levels[v] = level


                
                
    caches.append(cache)
    for v in cache:
        if v in target:
            target.remove(v)

    if len(target) == 0:
        break

result = "_=%?%?<<?!+?!+?!;$>"
for line in [caches[levels[ord(x)]][ord(x)] for x in targetStr]:
    result += "<<_%(" + line + ")"

print result

日記

mixiでこっちの日記の更新情報が見える設定にしました。


__ 渡辺さんの日記から

どうでも良いことだが、知能は「計る」ものなのか、それとも「測る」ものなのか、はたまた「量る」ものなのか。ある意味「謀る」ものではある。

えー、その点については地球上で最も知識量の多い知能だと思われる「Google先生」に諮ってお答えしたいと思います(ぇ)

  • "知能を謀る" 0件
  • "知能を量る" 0件
  • "知能を諮る" 21件
  • "知能を計る" 371件
  • "知能を測る" 500件
  • "知能を図る" 1210件

な、なんだってーΩΩ Ω


__ むー。Rubyで`foo %s` % barってやったら文字列の埋め込みよりコマンドの実行の方が先に起こるのか…。パイプでシェルにつなぐか…(ぇ)

pythonみたいに"%c%c" % (45, 45)とやるとrubyではエラーになるんだなぁ。


__ なんだかささださんがぶーぶー言うので作ってみました(ぇ)

西尾泰和のブログ: Just Another Ruby/Python Hacker,

攪乱する要素を入れなかったので、括弧や<<の繰り返しがきれいです。優先的に$(と$)を使うようにした方がよかったかな?

試しに使う記号を"(){}+-*%"に限定してみたけども、結局<<の繰り返しが区切りになって短い単位で読解できるのであまり読みにくくなりませんでした。数値計算部分で<<(?)-?()なんかを使うと攪乱できるのかも。<<(?(-?))も有効。あとは?)-?(を使って括弧を頼りにした読解を邪魔してやれば…。

やってみました。