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

2006年11月30日

執筆日記

わかった。 文章を書いたときにこまめに保存するのは習慣になっていて、 ブラウザ上で直接ブログの記事を書いた場合は保存即公開だけど、 Meadowで書いた場合は保存してから公開するまでにもう一作業いる。 で、保存したいという欲求はすごく強いけども、 公開の方はべつにさほどではなく「してもいいよ」という程度なので、 Meadowで保存したら満足して公開するのを忘れるのだ。そうに違いない。

この前の 西尾泰和のブログ: MeadowからGRINEditを操作する を利用してMovableType APIを叩けば新規追加は簡単にできるだろうと思う。 問題は更新で、既存記事を更新するためには当然既存記事のIDが必要になるわけだがそれをどうするか。

MovableType で使える XML-RPC API によれば、blogger.newPostで新規投稿できて、そのIDが返ってくるそうなので、 それをローカルのファイル名と対にしてどこかに保存しておけばいいのか。 howmで書いているのでファイル名が変更される可能性は考えなくていいし。

それをやるモチベーションはあまりない。


= AutismSNS(オーチズムSNS) に招待してもらいました。
= いまやっとWinXPをVMWareにインストールしています。 これでEclipseとかJythonとかをインストールする過程のスクリーンショットを撮るの。 締め切りが11月中(自分で設定した) 明日は人と会う用事がある。 うひゃー。

でもまぁ、別に頭を使う作業でも、悩むこともないので締め切りまでにはできるだろう。

VMWareを使うとインストール作業中に別の作業ができて楽。 でもXPの入っている中古のマシンを買うのと比べてどうかというと、 どうなんだろうね。


= Jythonのインストールをしてから Eclipseのインストールの説明をするつもりだったのに WinXPってインストール直後の状態だとJREが入ってないんだなぁ。

まさかSourceForgeからダウンロードしようとしてブロックされるとは。 IEほとんど使わないから忘れてた。

zipファイルをダブルクリックしたらデフォルトでは解凍されずに中を開くのか…。

再インストールとかしたときに アーカイバとタブブラウザのインストールは 真っ先にやってしまうから デフォルトの環境がどうなっているかってのは忘れてしまう。 一応Windowsの機能でzipを解凍してもらおう。

うぐぅ。 Windowsの展開ウィザードを使って展開すると、 「一部のファイルはブロックされました」 なんてメッセージが出る。どのファイルがブロックされてるのかの一覧を出して欲しい。 ダブルクリックして開いたところからコピーする方がよいようだ。

余計なことがいちいち気にかかってしまう。 「URLは~~」と書こうとして「あれ、URIの方がいいのか?」などと。 で検索して調べてやっぱりURLにしとくことに。

なぜか急にマシンが重くなったと思ったら、 VMWareの中のWindowsが更新をダウンロードしてた。 そりゃ重いや。 キャンセルしたくてもなかなかできないくらいに重い。 そして結構眠い。 更新をダウンロードさせたまま寝ようかな。

日記を貼り付けて寝ようと思ったけど、 Firefoxが全然動かないので諦めた。 EclipseとかFirefoxって、しばらく放置して別の作業してから戻ると、 メモリの上に乗っていた情報がハードディスクに追いやられていて 元通り動くようになるまでに結構時間がかかるよねぇ。 メモリを10ギガくらい積んであるとこういうときにさくさく動くのだろうか。 しかしノートなのでメモリをそんなに拡張できる時代はまだまだ先だろう。

ちょうど今、二台目のマシンにWinXPをインストールしていたのが完了したようだ。 KNOPPIXが動くことを確認して買ってきたのに、結局面倒になって放置していて、 合法的にWinXPのディスクを手に入れたので「これでいいや」ということに。 結果としては5万円ちょいでちょっと小さくて残像の残りやすいテレビを買ったことになるのかな? まぁ、プログラマブルなテレビということで、損ではなかろう。


= 金田一耕助という架空の名探偵のことと、 八つ墓村、犬神家の一族、悪魔が来りて笛を吹く、という小説の名前は知っていたけども、 この小説が金田一耕助シリーズだということは知らなかった。 っていうか推理小説だったのか。ホラーだと思ってた。

2006年11月29日

Re: 先頭から2文字ずつ取る

Pythonのジェネレータで四角いらせんを書くのに反応した|Pythonでなんか作ってみるの隣のエントリー先頭から2文字ずつ取る|Pythonでなんか作ってみるに反応してみます。

これでどうでしょ?

>>> def foo(a, b, *rest):
	c = "0x%c%c" % (a, b)
	if not rest:
		return [c]
	else:
		result = foo(*rest)
		result.insert(0, c)
		return result

	
>>> foo(*"123456")
['0x12', '0x34', '0x56']

ジェネレータが使えるならこっちの方がいいかも。

>>> def foo(a, b, *rest):
	yield "0x%c%c" % (a, b)
	if rest:
		for result in foo(*rest):
			yield result

>>> for result in foo(*"123456"):
	print result

	
0x12
0x34
0x56

2006年11月28日

MeadowからGRINEditを操作する

odz buffer - coLinux で Emacs の kill-ring の内容をWindowsのクリップボードと同期するを参考に、とりあえず試してみました。 単に選択範囲の文字列をGRINEdit上に出すだけですが。

使用前

使用後

Emacs側

(defvar GRINEDITPY "grinedit.py"
  "*The command to send query to grinedit")

(defun grinedit (beg end)
  (interactive "r")
  (call-process-region 
   beg 
   end 
   GRINEDITPY))

(define-key global-map "\C-cg" 'grinedit)
call-process-regionでgrinedit.pyを呼んでいます。 選択されたリージョンは標準入力に流し込まれているみたいでした。 環境によって違ったりするのかも知れません。EmacsLispは詳しくないので。

grinedit.py

import xmlrpclib, sys
text = sys.stdin.read()
server = xmlrpclib.Server("http://localhost:8080/RPC2")
g = server.grinedit
g.initGraph()
for line in text.split("\n"):
    g.addVertex("BoxVertex", {"label": line})
grinedit.pyは標準入力に流し込まれた文字列を改行で区切ってGRINEditにXML-RPCでクエリを投げるだけ。

合計でも20行いらなかったですね。 後は個人的にはMeadowで箇条書きを書くとGRINEdit上にマインドマップ状のものが生成されるようにしたいところです。まぁ今回試したこれが動くのなら、技術的には難しくなさそうです。

Demo: Dynamic Law Replacement

Demo: Dynamic Law Replacement

2006年11月25日

エスパー日記

今日は神戸国際会議場で未踏集会 ESPer2006 秋の陣

__ 昨日の日記貼り付け忘れていたのに気がついたので下に貼り付け。 やっぱり早いところhowmとMovableTypeを同期するようにしないとなぁ。 これブラウザの側で貼り付けているので、後でうっかりhowm上の日記で上書きしないように気をつけないと。


__ Amazonはいつの間にか「お急ぎ便」なんてオプションが増えてますね。 朝の2時に注文してたのですけど、「今日届けます」と書いてあってびっくり。 2~300円くらい送料が上がるだけみたい。 何か急ぎの時は使うとします。 急いでネットで本を買わなきゃいけない時ってどういうシチュエーションだろう。


= howmにもだいぶ慣れてきました。 Meadowにも。 まだMeadowとEclipseを切り替えて使うと Eclipseで保存をするときにCtrl+X Ctrl+Sと押してしまったり、 Meadowで保存をするときにCtrl+Sと押してしまったりしますが、 実害がないのでまあそのうち慣れるでしょう。

区切りに日時が入るのはブログに貼ったときに目障りなのでやめました。 逆に、日記を書くときにC-,cした後そのまま書き始めると 後で一覧を見たときにどれが日記かわかりにくなってしまうので まずはタイトルに「日記」と書くようにしようと思います。

あっサクラエディタでC-xC-sすると、1行消してから保存してしまう(笑)


= 「Pythonから辞書がなくなったらPythonを使うのをやめるだろう」とか 「Pythonの長所は名前空間が辞書だという所じゃないだろうか」 とか考えていたのですけど、 もしかすると「名前空間がファーストクラスのオブジェクトである」 と表現するのが一番適切なのかも知れません。

C言語しか知らず、C言語の考え方でプログラミングをする人にとっては、 「関数がファーストクラスのオブジェクトではない」 と感じることすらありません。 しかし一度PythonやSchemeのような関数がファーストクラスのオブジェクトであるような言語を使うと、 たとえC言語で関数ポインタを使って似たようなことができたとしてもはがゆく感じるようになります。

あまり意識されていませんが、例えばglobals()で取得できる辞書は グローバル名前空間のコピーではなく、 この辞書に対して普通の辞書と同じように操作ができ、 操作は名前空間に反映されるという意味で「グローバル名前空間そのもの」です。 例えば変数が定義されているかどうかを返すundefのような構文がPythonにないのは、 名前空間が普通の辞書なので普通にキーが存在するかどうかを試すメソッドを呼べばいいだけだからです。 こういうように「名前空間がファーストクラスのオブジェクト」という特徴によって シンプルかつ柔軟にまとまっているという点もPythonの長所なのではないでしょうか。


= GRINEdit alpha0.20の公開のために、 サンプルが全部きちんと動くか確認作業。 で、XML-RPCのデモを動かしていたときに XML-RPCのデモなのに途中で範囲選択して剛体化するのは変だと思ったので修正。 「g.addLaw("PL_RigidBody", {"target": vs})」と1行書くだけで、 頂点のリストvsを剛体化することができるようになった。 Javaのコードは10行も変更する必要がなかった。もっと早くやっとけばよかったかも。

将来的には範囲選択した頂点をXML-RPCで取得できて、 それに対して何か処理をしたりとかできるというデモにすればいいと思うんだけど、 今はまだ選択範囲をXML-RPCから取得できないからね。

選択範囲をXML-RPCから取得できるようにする変更を加えないといけないのをすっかり忘れていた。 howmのTODOに入れるだけじゃなくてTracのチケットにもしとかないといけないのか。 「ポケットは一つ」の原則はなかなか守りづらい。


= あー。びっくりした。 行きの電車の中でマシンを起こしたらキーボードが全然反応してなくて焦る。 再起動してもなおらず、 キーボードを分解して掃除してもなおらず、 キーボードに関係しそうなねころがーをアンインストールして再起動してもなおらず、 モニタ回転ボタンを押して「これは反応するなぁ」とか、 ボリュームボタンを押して「これは反応するなぁ」とか試していたら、 いつの間にかなおった。謎。 そんなことをしていたらいつの間にか目的駅に着いていて危うく降り損ねるところだった。

今日は体調が悪い。

油井さんのデータベースの話は難しくてよくわからない。 平林さんの検索エンジンは使いたい。 普段Googleで不満に思っている「\magで検索できないじゃん!」とかが解決されそう。

頭痛くなってきた…。

アーテインのグラディエイターというゲームは専用スクリプト言語から プリプロセッサでC言語に変換して作ってるんだそうな。

空目が激しかった。ぬいぐるみのための壁紙って何だろうと思ったら型紙だった。 なるほど。実際にきちんとぬいぐるみができている。これは便利。

最近は結婚式の時に自分の生まれたときの重さのテディベアを親に送るのが流行ってるんだそうな。 たぶん新婦限定だろうけど。

空気での造形にも応用できるそうな。

わっふるはWAFfull。 Web Application Firewallなんとかの略。 まだ公開されていないので「ぐぐるな危険」。 httpd.confに記述するだけで、フィールドの値のバリデーションとか、 改行やヌル文字を空白文字に変換するとかそういうことができるらしい。 CGIがどういう言語で書かれているかとかが関係ないので 穴が見つかったときにすばやくふさぐことが可能。

DFAとかってなんだっけと思って検索したら決定性有限オートマトンのことだった。

食品衛生局って何だっけ。FDAだっけ。

あのBayoNetを作った人がモデライズ株式会社というベイジアンネットでモデリングをする会社を設立。

ベイジアンネットは最初のモデルのトポロジーを決定するところが難しいと思っていたのだけど、 評価グリッド法というものを使って初期パラメータの決定を行うらしい。

ベイジアンネットを利用するためのノウハウが高度なんだそうな。

影舞はカゲマイと読むのか…。

ウノウの椅子はバランスボール(誇張)

寒いよう。 昨日暖かかったので油断した。

ウノウは色々面白い。 出張オフィスは面白いかも。 二ヶ月に1回2泊3日で無線LANと24時間入浴可能な温泉のある宿に行って 通常業務以外のことをなんでもいいからとにかくやるんだそうな。 僕みたいにマルチタスクの苦手な人間にとっては、 毎日業務と業務以外をやるより、 業務以外のことばっかりやるフェーズがあるのの方が適しているかも知れない。

テスト番長はどう見ても番長w

KLabはクラブと読むんだって! ケイラボだと思ってた! 会社は六本木にあるから 「六本木のクラブ」なんだそうな(笑)

ピンキリってピンが上だっけ? ピンが1でキリが9だった気が…。調べてみたら、 ピンが1で、一番いいんだそうな。

知能集約型vs労働集約型。 知能集約型は優秀な学生の一本釣りとよくマッチするが、 労働集約型では試験で休まれたり遠隔地に散らばっていたりすると難しい。

冷えで喉がいがいがしてきた。


= 懇親会。二次会。三次会。四次会。 朝まで生討論。 GRINEditが目指しているものは、 グラフの可視化ソフトだ、 と説明するのが世間的には理解しやすいのだろう。 インタラクティブで、フォーマットが腐っていなくて、 拡張性の高いものを作ろうとしている、と説明するのが受け入れられやすい説明だろう。 しかし、それは第一コーナーであって、ゴールじゃない。 世の中の自然言語はきっと全て一次元的だが、 それはその自然言語が発生する過程で一般的だった声&耳という通信デバイスが 一次元的な記号列の通信に適していたからに過ぎない。 まずは音声に記号列を乗せて通信する方法が発明され、 それからそれを永続化する手法として文字が発明された。 紙の発明によって記号列の保管コストが下がった。 活版印刷が発明され、記号列の生成コストが下がった。 コピー機が発明され、記号列の複製コストが下がった。 電信の発明により、記号列を配信するコストが下がった。 そしてご存じの通り、コンピューターが現れ、 インターネットが現れ、すさまじいコストの低下をもたらした。 そしてその時代に、人間が自分の脳内で作り出された情報を他者に通信する手段は 旧態依然の一次元の記号列を使っている。 これはIDEが使える時代なのにハンドアセンブルでプログラムを書いているようなものなのではないか。 ハードディスクが使える時代なのにパンチカードを使うようなものではないか? 僕はそこをなんとかしたいんだ!

というようなことを話したような気がする。

質疑応答。「Q:君がやろうとしていることは人間を進化させることか?」 A:携帯電話の普及により、多くの人が遠隔地の人間とコミュニケーションする能力を獲得した。 これを進化と呼ぶのなら、僕がやろうとしていることももちろん進化だろう。

他にもチューリングテストやバベルの塔、 記号と確率とどちらが根源的か、なんて感じで色々盛り上がったのだけど、 どういう流れでどういう話だったか説明できるほどには覚えていない。

でもまあ、僕は「記号こそ本質で確率はまやかし」という意見には同意できないと思った。 人間が生得的に持っている素朴物理学が、実際の物理学とは一致しないのと同様に、 人間が生得的に持っている観測デバイスにも性能の限界があり、 外界を正確には観測できていない。 人間は、実際には分布の標準偏差が小さいだけなのに 勝手にデルタ関数だと思いこんだり (ディラックのデルタ関数 - Wikipedia)、 メンバシップ関数の値がほとんどの場合において1か0であるというだけの理由で それをクリスプな集合だと思いこんだりする。(ファジィ - Wikipedia)

あるコンピュータのCPUがポンコツで、実数値をたかだか十数桁の精度でしか扱えない、「考える際には丸めないといけない」ものだったからといって、実数という概念より浮動小数点数という概念の方が本質的かというとそうではない。 実数の方が、浮動小数点数よりも、よりシンプルでパワフルな概念だ。 ハードウェアがポンコツなせいで実装が浮動小数点数でなければいけないとしても、理想的なモデルは実数であるべきだ。 実数の概念なしで物理学を構築したら、バッドノウハウだらけのゴミの山が築かれ、いずれ行き詰まる。クォータニオンなしで3Dのプログラムを書いたら、いずれ行き詰まる。 狭き門より入れ。

同じことで、人間が一旦記号列に落とさないと他人とコミュニケーションしながら考えたり、 考えたことをシリアライズしておいて後で再開したりすることができない、というのは 人間というハードウェアがポンコツなだけだ。 それのポンコツハードウェアにとらわれていてはいけない。 実際、芸術家や囲碁棋士は記号列を使わない思考方法が可能であることをよく示していると思うし、 自分自身も記号列ではない思考を行っていると思う。

2006年11月23日

1行でテトリス

今日のDjango勉強会で もっと短いPythonのテトリス ― TRIVIAL TECHNOLOGIES 2.0 を教えてもらったけど、15行で書かれたテトリスがリンク切れで読めません。

なぜ15行なのか。なぜ1行にしなかったのか。できなかったのか。 15行版のソースコードが見られないので謎です。

そこで自分で作ってみることにしました(ぇ)

追記。これはNikolaj Baer: Stepping it up a notch: Tetris in 100のコードを1行に縮める過程です。


= 2006-11-23 01:26:55 pygame - python game development をインストール。 Windows用インストーラがある。ダウンロード中。 Enterを5回押すだけでインストール完了。 とりあえず100行テトリスを コピペして動かしてみる。動いた。 X印で終了しようとしたら固まった。 まぁいいや。
= 2006-11-23 01:32:36 とりあえずsvnリポジトリ作成。37分。 ソースを眺める。 いろいろなものがglobalに直に置かれている。 gという変数は使われていないようにみえるのでこれを「globals()」 (グローバル名前空間)にしよう。
= 2006-11-23 01:45:43 最初の代入文のかたまりをさっそく今日覚えた 辞書のupdateのキーワード付き引数で変更。 次はrender関数の中へ。うわー、インデントがスペース3文字だ。 elseの後に改行なしでコード書いたりしてるー。 こういうコードは許せないのでとりあえず整形(どうせつぶすのに)

さて、ここで使われている変数cはローカル変数だ。 if文で変数の値をセットして後で1回使うだけ、ということは、 これは変数を使っている部分に条件込みの式を一つ入れれば済む話。

renderの中身は無事1行に。

現在1時55分。


= 2006-11-23 01:56:00 updateを利用すると、今までglobals().__setitem__("foo", 1)と書いていた代入文が かなり楽に書けるようになる。 たいがいのプログラムにある変数の初期化部分で
globals().update(g=lambda **kw:globals().update(kw), ...
と書いておけば、以降はg(foo=1, bar=2,...)と わりと普通に代入文が書けるようになる。
= 2006-11-23 02:09:27 今回は、他人のコードで、Pygameの仕様にも詳しくないので、 挙動を変えないような書き換えが必要。 たとえばすでに一部書き換え済みだけど下のような例。
   keys=pygame.key.get_pressed()
   keys[pygame.K_LEFT] and px > 0 and g(px=px-1)
   keys[pygame.K_RIGHT] and px+len(piece.split('\n')[0]) < bw and g(px=px+1)
   keys[pygame.K_SPACE] and g(py=drop_piece(piece,px,py))
   keys[pygame.K_RETURN]and g(piece=rotate_piece(piece))
この場合、pygame.key.get_pressed()を1回呼んでいるのを、 4回の呼び出しに変えてもいいかどうかは仕様による。 「前回呼ばれてから次に呼ばれるまでに押されたキーを返す」 という実装になっている可能性も大いにある。 でも調べるのは面倒なので、1回の呼び出しでいいようにする。 1回代入して複数回使うケースを、代入を使わずに実現するにはどうすればいいか…。 うーんと。 ラムダ関数の引数にする手もあるけど、 この場合は使われ方が同じだからデフォルト引数を使う方がスマートかも。 Pythonのデフォルト引数は定義時に評価されるので
   lambda key,keys=pygame.key.get_pressed(): keys[key]
こういう関数は何回呼び出しても関数定義の1回だけget_pressedが呼ばれる。 あとは下のようなリスト閉包で真偽値のリストに変えて…
[
    (lambda key,keys=pygame.key.get_pressed(): keys[key])(key)
    for key in [pygame.K_LEFT, pygame.K_RIGHT, pygame.K_SPACE, pygame.K_RETURN]
]
条件が真だった場合に実行すべき内容を、 評価を遅延させるためにlambdaで囲ったリストとzipして、 条件が真だった場合にその内容を評価するような関数にmapで渡す。
map(lambda (x,y): x and y(),
    zip([
       (lambda key,keys=pygame.key.get_pressed(): keys[key])(key)
       for key in [pygame.K_LEFT, pygame.K_RIGHT, pygame.K_SPACE, pygame.K_RETURN]
    ],[
       lambda :px > 0 and g(px=px-1),
       lambda :px+len(piece.split('\n')[0]) < bw and g(px=px+1),
       lambda :g(py=drop_piece(piece,px,py)),
       lambda :g(piece=rotate_piece(piece))
    ])
)

= 2006-11-23 02:36:07 renderとtickをnext_pieceをlambda関数に変えて、 最初の変数の初期化の行にくっつける。 結局のところ関数の宣言も変数の初期化なんだ。 値が無名関数なだけで。
= 2006-11-23 02:40:49 rotate_pieceは面倒なことをしてあるね。 素直にfor文を二重にすれば楽なのに。
def rotate_piece(p):
   pp,pl="",p.split('\n')
   for i in range(len(pl)*len(pl[0])):
      pp+=pl[len(pl)-1-i%len(pl)][i/len(pl)]
      if i%len(pl)==len(pl)-1: pp+='\n' 
   return pp.rstrip('\n')
こう書かれていたけど、まず下のように直す。
def rotate_piece(p):
    pp,pl="",p.split('\n')
    for i in range(len(pl[0])):
        for j in range(len(pl)):
            pp+=pl[len(pl)-1-j][i]
        pp+='\n' 
    return pp.rstrip('\n')
次にすること: 中のfor文が終わった後改行文字をつけておきながら、 最後にreturnする前で最後の改行文字を取り除いている所に 「"\n".join使えよ!」とつっこむ。
def rotate_piece(p):
    pl=p.split('\n')
    return  "\n".join([
            "".join([pl[len(pl)-1-j][i] for j in range(len(pl))])
            for i in range(len(pl[0]))
    ])
あとはplへの代入を取り除く。どうしようか。 これはlambdaを使うのが一番楽かも。
def rotate_piece(p):
    return  (lambda pl:"\n".join([
            "".join([pl[len(pl)-1-j][i] for j in range(len(pl))])
            for i in range(len(pl[0]))
    ]))(p.split('\n'))
忘れずにコミットしなきゃ。まだリビジョン6なのはコミットし忘れが多いせいだ。
= 2006-11-23 02:52:04 drop_piece。while文が出てきたけど、せいぜい20回程度のループだから、 再帰呼び出しで問題ない。
drop_piece = lambda p,x,y:
   (y <= bh-len(p.split('\n')) and \
           not(collide_piece(p,x,y+1)) and \
           [drop_piece(p,x,y+1)] or [y])[0]
collide_piece。forの中で本当にreturnしようとするとちょっと面倒だけど、 この場合は実行される内容に副作用がない(と思える)ので、全部計算してから 「True in ...」でTrueのものがあるかチェック。
= 2006-11-23 03:11:28 深刻な問題。 飽きてきた。

深刻な問題2。 キムチ鍋をした後ほったらかしていた鍋の表面にびっしり白いものが! 開けたらすごく臭い! どうしよう!

とりあえず中身を捨てたが多少こびりついている。 気持ち悪いから洗いたくないので水を張って台所用漂白剤を多めに入れてみた。 吉と出るか凶と出るか。吉なら、明日の朝には分解されてなくなっている。 凶なら変な反応が起きてさらに気持ち悪いものができている。


= 2006-11-23 03:16:52 fix_piece。それglobal文いらないから、とツッコミ。
= 2006-11-23 03:23:42 そうか、なんでやる気が続かないかわかった。 今回は、改行を詰める作業は手作業でやらずに、 最後にスクリプトで不要な空白文字を取り除かせようと思っていたのだけど、 そのせいで行数が縮まないから達成感がない。今93行。

今まで書いた部分だけ余計な空白文字を取り除いてみた。 36行になった。1画面に収まった。やる気出た。

chk_board。割とめんどくさいなぁ。 そろっている行を消す処理なんだけど。 ただ消すだけならfilterでそろっているのを取り除けばいいんだけど、 まとまって消えたときにスコアが高くなって欲しいそうだ。 しかも1行と2行に分かれて消えたのはまとまって3行消えたのとは違う点数。


= 2006-11-23 03:58:13 続きの代入文は面倒だからセミコロンでつないでしまった。 トップレベルだからこれでも問題なく動く。 最後のwhile文は繰り返し回数の多いループだから itertoolsのcountとifilterを使う。 できあがり。 1行です。2695文字だけど。 お、ちょうど28時ジャスト。 今回は無駄に長い変数名などがあるのでもっと縮めるのも簡単だけど、 それはもう飽きたのでやりません。

__ 15行バージョンが見られました。80*15行の「ワンライナー」だったようです。 変数名を短いものに置き換えたり、オリジナルの関数をそのままワンライナー化しないで可能であれば展開したりという方法でかなり短くできたようです。でも「import random,pygame;」と「P=pygame;」は「import random,pygame as P;」にすればもっと縮まりますね。個人的にはfindで部分文字列が見つからなければ-1が返ってくることと、-1のビットNOTが0であることを利用して「0のない行(全部詰まった行)を取り除く」というのを「[r for r in B if~r.find('0')]」と書いているあたりがかなりクールだと感じました。

Django勉強会とか日記

アメリカでしか買えないものでもこれを使えば買えるかも、だそうな。 Mail Forwarding Leader - Your Very Own U.S. Mailing Address - Mailforwarding 朝ご飯に食べようと思って買ってきたプチトマトが、 パッケージを開けてみるとカビまみれだったり半分腐って解けて流れていたり。
= 2006-11-22 12:13:30 ThinkGeek :: Grow Your Own 1up Mushroom Kit。 デザインおかしいよ。ハテナブロックから出さないと。 X51.ORG : 町中に設置されたスーパーマリオのハテナブロックに爆弾処理班が出動 米
= 2006-11-22 15:58:18 防災訓練。 地震を体験できる車に乗ったけども、地震の怖さはあんまり伝わらないですね。 てんぷら揚げてるときに揺れたり、本棚が倒れてきたりしないので。
= 2006-11-22 16:19:20 WindowsXPのアカデミックパックにはアップグレード版しかないようだ。 うーん。通常版を買うか、2000でやるか。
= 2006-11-22 18:08:34 今日はDjango勉強会。 しまった。ラボにあんパンを忘れてきた。
= 2006-11-22 18:14:50 strとunicodeはbasestringの子
>>> isinstance("aaa", str)
True
>>> isinstance(u"aaa", str)
False
>>> isinstance(u"aaa", unicode)
True
>>> isinstance("aaa", unicode)
False
>>> isinstance("aaa", basestring)
True
>>> isinstance(u"aaa", basestring)
True

= 2006-11-22 19:15:24 Django勉強会。

あらかじめBlogの名前を聞かれたのでどういうことかと思ったら 名札にBlog名が付いていました。なるほど。 real nameとhandle nameの対応がつきやすくなるのでいいかもしれない。

AMFというのは知らなかったけど ActionScriptでサーバと通信したりするフォーマットらしい。 OZACC.blog: Django AMF を使うと、Flashからの通信をDjangoで受けて色々するのが簡単にできるらしい。

Flashだとかっこいいグラフを書くのも楽かも知れないなぁ、と思いつつ、 GRINEditに関しては、やっぱりJavaアプレットで作るのが 今のコードを再利用できるから楽だろうなぁ。

DreamHost

「manage.py dbshell」でDBの対話式になる。

今日はDjango再入門 RandomNoteを作る vol.1 下準備 (ueBLOG)のペアプログラミングをしてきました。

MySQL自体は以前PHPのウェブアプリをいじったときに入れてあったのだけども、 PythonからMySQLにアクセスするライブラリMySQLdb (SourceForge.net: MySQL for Python) を入れていなかったのでにっちもさっちも。 PHS接続でダウンロードするのは時間がかかりそうだったのでsqliteを使う方針に変更。

sqliteを使うときはデータベース名(DATABASE_NAME)が データベースファイルのフルパス (Windowsなら例えばC:/から始まるもの)でなければいけない。 ユーザやパスワードは必要なくなる。

python manage.py dbshellでsqliteの対話式に行こうとしたけど、 sqliteにそもそもパスが通ってなくて失敗。 パスを通してコマンドプロンプトを起動し直したが、 どうもうまく動かない。sqliteのコマンドを入れているのに、 そんなDOSコマンドはない、という反応をしたりして謎。 追求するのは面倒なのでsqlite3を直接起動した。

結局2章の途中までしかいけなかった。 続きはまた今度。

飲み会。

for文のelse節は便利だけど、なくても別にいい。 ジェネレータも便利だけど、なくても別にいい、 っていうかできる前から使ってたし。 というようにPythonの機能をちょっとずつはがしていったときに、 何がなくなると嫌か、何がなくなったら Pythonじゃなくて他の言語をメイン言語にするか。 そう考えた。「辞書」かもしれない。 「名前空間は単にキーが文字列の辞書」これがイイ。 なぜこれができるかというと、 文字列が破壊できないオブジェクトだから。 RubyでSymbolをStringの子にするかどうか云々の議論がされているときに、 「なんでSymbolが必要なんだろうなぁ」とぼんやり考えていたんだけど、 結局「Pythonの文字列はimmutableだから、わける必要がないんだ」 という結論に達した。 文字列が変更不可能なオブジェクトであることのデメリットはなんだろう。 replaceなりcapitalizeなりを呼んだときに、 新しいインスタンスが生成されるから多少余計に時間がかかるかも。 ゲノムの解析みたいなので、 1ギガのファイルをメモリが2ギガしか積まれていないマシン(笑) で読み込んでraplaceを何回かかけたりすると 体感可能な実行速度の差が出るかも知れない。 でもこの場合はもちろんそんなでかい文字列をメモリに全部読もうという 富豪的発想がまずいとも言える。

Emacsのetcディレクトリの中には色々変なものが入っている。 sで始まる5文字のファイルなんかとあるコマンドのマニュアルなんだけど 多種多様なコマンドラインオプションが解説されていてすごい。 最古のプログラムだと書かれているけど、 すでにこちらの画像をすべてのピアに送信するオプションがあって、 P2Pによるファイル共有の先駆けといえるかも知れない(無理矢理)

dictが色々できるのをはじめて知った。 dictとupdateの違い。 辞書(dict)のコンストラクタに キーワード付き引数を渡すと新しく作られた辞書に そのキーワードと値の対も入る。 また、第一引数として辞書を渡すとその辞書のエントリーも入る。 辞書のupdateメソッドも同様に、第一引数に辞書を渡したり、 キーワード引数で渡したりできる。挙動はほぼ同じ。 ただし、dictは新しいオブジェクトを作成するのに対し、 updateはレシーバを破壊的に変更する。

次にDjangoをいじるのはいつになるかなぁ。 春に出る本には1.0という言葉が(1.0がすでに出ているものとして)登場するので それまでにはきっと出るだろうとのこと。 4月になってから使おうかなぁ。


= 2006-11-23 04:13:30 またつまらないものを作ってしまった(五右衛門の声で)。 西尾泰和のブログ: 1行でテトリス

SourceForge.net: python-mode.el for Emacs and XEmacsを入れた。 配色が微妙だ。調整しないと気に入らない。 1行Brainf*ckインタプリタを作ったときに作ったPythonワンライナー圧縮プログラムにかけたら 1980文字に縮まったけど、シングルクォーテーションやバックスラッシュを適切にエスケープしていない のが原因と思われるバグで動かない。もういいや。今度気が向いたときにでも。

2006年11月21日

ループする写真

秋元@サイボウズラボ・プログラマー・ブログ: ループする写真。 最初、写真の中に写真の中に写真の中に…というループだと思ったのだけど、よく見たら額縁がらせんになっている。手が込んでいる。っていうかどうやってつくるんだろう。例えば青い紙の入った額縁を持って写真を撮り、適当なライン(たぶん左上隅)で切断して、半径方向に螺旋状に縮ませる。縮んだ側が縮んでない側の0.6倍だと仮定するとその螺旋状に縮ませたものを0.6倍にしたもの、0.36倍にしたもの…を青い部分を透明色で抜いて重ねていけば無限のらせんができる。実際には人の目でわからないくらいまで小さくなったら一周する毎に一周手前にジャンプしてもばれない。原理的にはそういうこと何じゃないかと思うけども、わざわざ単なる縮小らせんじゃなくてひずませてねじれながら入っていくようにしているのが手が込んでいる。あ、でもそれもどうせ螺旋状に縮小するコードを自分で書くんだったら360度の輪っかを少し開いて350度とかにすればいいだけだからさほど難しくないのかな。明日電車で座れたらPILで試してみようかな。

と思ったけど、一晩経ったら人が作ったものの劣化コピーを作っても楽しくないのでやる気がなくなった。

2006年11月20日

一般化したハノイの塔問題にひそむ規則性

これは2006年冬のプログラミングシンポジウムの GPCCの会議で出た「棒の本数が4本以上のハノイの塔はどうなるのだろう」という疑問について、 1月15日に走り書きして放置していた結果( 西尾泰和の日記(2006-01-16) )を清書したものです。

ハノイの塔問題を知らない方は ハノイの塔 - Wikipedia を参考にしてください。 従来のハノイの塔問題では、棒の数は3本でした。 この場合、板が1枚ならば1手で動かせますが、 2枚の場合は1枚目を脇にどけて2枚目を動かし1枚目を2枚目の上に戻す、 という3手がかかります。 これを、板の枚数2とスタートとゴールをのぞいた 「一時待避用の棒」の本数1とを用いて 「hanoi(2, 1) == 3」と表現します。 また、この待避用の棒が1本あることを 「スペースが1個ある」と表現します。 スペースが1個のハノイの塔問題に関しては 「hanoi(n, 1) = 2 * hanoi(n - 1, 1) + 1」 が正の整数nに付いて成り立つことが知られています。 スペースが2以上の場合には、いったいどういう規則性があるのか、 それを確かめてみました。

スペースが1個の場合の最小手数は、板の枚数が0枚の時の0手から順に

0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, ...
となります。 スペースが2個の場合、3個の場合の最小手数は、
0, 1, 3, 5, 9, 13, 17, 25, 33, 41, 49, 65, 81, 97, 113, 129, ...
0, 1, 3, 5, 7, 11, 15, 19, 23, 27, 31, 39, 47, 55, 63, 71, ...
となります。 この数列の隣り合う項の差を取る(階差数列)と、それぞれ
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, ...
1, 2, 2, 4, 4, 4, 8, 8, 8, 8, 16, 16, 16, 16, 16, ...
1, 2, 2, 2, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, ...
同じ数がいくつ続くかを新たな数列にすると、スペースが1個、2個、3個の場合にそれぞれ
1: 1, 1, 1,  1,  1, ...
2: 1, 2, 3,  4,  5, ...
3: 1, 3, 6, 10, 15, ...
となります。 また、この数列の列はパスカルの三角形を45度回転して斜めに読んだものです。 (パスカルの三角形 - Wikipedia)
             1
           1   1
         1   2   1
       1   3   3   1
     1   4   6   4   1
   1   5  10  10   5   1
 1   6  15  20  15   6   1
スペースが3個の場合の数列は三角数と呼ばれるものです。 (三角数 - Wikipedia) つまり、スペースがm個のハノイの塔の最小手数の数列の階差数列は、 m次元の三角形を用意して、 0段目には1、1段目には2、k段目には2kと書き、 小さい順に読みあげたものだと考えられます。スペースが0個のハノイの塔で 1枚しか移動できないのは、0次元の三角形(つまり点)になってしまうからです。

ひとたび規則性がわかってしまうと、その規則性が何に由来するものなのかも想像しやすくなります。階差数列が2になっているのは、1枚板を増やしたときに最小手数が2増えるということです。2はスペースがmの時にm個続くのですが、これはつまりm個スペースがあれば、m枚までの板は積み重ねずに平たくスペースに並べられることによります。そして4が続く領域では「一度小さい板を空いているスペースに置いた後、大きい板を別のスペースに置き、スペースが足りなくなったので小さい板を大きい板の上に移動する」という作業が行われています。この時、スペースがm個なら、最初に平たく置くことができたm枚のうち、小さい方のm-1枚は一番大きい板に乗せることができ、残ったスペースはm-1個になります。これが繰り返されることで三角数が現れるわけです。上のストーリーでは横方向が三角数になることに注目していましたが、実は縦方向が三角数になるということの方が根源的なのかも知れません。

以下はソースコードとその説明です。

# -*- coding: cp932 -*-
#
# ハノイの塔の一般化
#

class CInfinity:
    def __cmp__(self, v):
        return 1

INFINITY = CInfinity()


def divide(x, y):
    if y == 1:
        yield (x, None)
    else:
        for i in range(1, x):
            for j in divide(x - i, y - 1):
                yield (i, j)

cache = {}
def hanoi(numPlate, numSpace):
    if numPlate == 0:
        return 0
    if numPlate == 1:
        return 1
    if numSpace >= numPlate - 1:
        return numPlate * 2 - 1

    if cache.has_key((numPlate, numSpace)):
        return cache[(numPlate, numSpace)]

    minHand = INFINITY
    for d in divide(numPlate - 1, numSpace):
        numHand = 0
        for i in range(numSpace):
            v = hanoi(d[0], numSpace - i)
            numHand += v
            d = d[1]

        if numHand < minHand:
            minHand = numHand

    result = minHand * 2 + 1
    cache[(numPlate, numSpace)] = result
    return result


result = [hanoi(n, 2) for n in range(100)]
print result
print [result[n + 1] - result[n] for n in range(99)]
最初のCInfinityは単なる無限大の定義です。 かわりに「十分大きな数」を入れても問題ありません。

次の関数devideはx個のものをy個にわける方法を列挙する関数です。 例えば5個のものを3個にわける方法を列挙させると以下のようになります。

>>> for d in divide(5, 3):
	print d

	
(1, (1, (3, None)))
(1, (2, (2, None)))
(1, (3, (1, None)))
(2, (1, (2, None)))
(2, (2, (1, None)))
(3, (1, (1, None)))

関数hanoiはnumPlate枚の板とnumSpace個のスペースがある場合の最小手数を返す関数です。 板が0枚の時は0手、1枚の時は1手です。 n枚でn - 1個以上のスペースがある場合は、 上からn - 1枚の板をそのスペースに待避させ(n - 1手)、n枚目の板を移動し、 待避させた板を順に元に戻す(n - 1手)だけでよいので、 最小手数は2 * n - 1手になります。 その次のif文は、 結果がすでに計算されている場合には計算し直さずにその結果を再利用しているだけです。

その先の10行程度が肝心の計算を行う部分です。 スペースが1個のハノイの塔では、for文などを使いませんでした。 それは1つに分割する方法が1通りだからです。 例えば6枚と2つのスペースのハノイの塔では、6枚目を動かすために5枚を待避させる際に、 何枚を1つめのスペースに移動し、何枚を2つめのスペースに移動するかで、 4通りの可能性があります。 また、2枚と3枚にわけるのと、3枚と2枚にわけるのでは意味が違います。 前者の場合、スペース2個を利用して2枚を移動するのに3手かかり、 次にスペース1個を利用して3枚を移動するのに7手かかります。 後者の場合は、スペース2個を利用して3枚移動するのに5手で済むので、 残り2枚の移動にかかる3手を加えても2手少なくなります。 6枚を2個のスペースを使って移動する際の最小手数を求めるためには、 全ての5を2つ(d1, d2)にわける方法の中で 「hanoi(d1, 2) + hanoi(d2, 1)」が最小となる数を求める必要があります。 スペースが3つの場合には3つに分割する必要があるので、 2つ目のfor文で手数の計算を一般化しています。

後は0以上100未満のnに付いてhanoi(n, 2)を計算すると、 スペースが2個の場合の最小手数の数列が得られます。 最後の3行では、その数列と、階差数列とを表示しています。

なお、このプログラムはPythonという言語で書かれています。 スペースが3つで板が0枚から99枚までの場合について計算するのには 4秒程度の時間がかかります。 スペースがもっと多い場合について検証する際にはご注意下さい。

悲しい

日記書いたのにアップされてない…。 久しぶりにhowmじゃなくて直接ブラウザに書いたのがいけなかったのか。 アップされていることを確認する前にブラウザを閉じてしまったようだ…。 (´・ω・`)

そしてもう朝の5時。寝よう。 結局「生活のリズムを直すために休日も8時起き!」という決意は3日坊主でした。ダメだなぁ。

2006年11月18日

反発力の計算が14倍ほど速くなった、他。

失敗談 grinedit.addEdge("LinearEdge", {"v1": v1, "v2": v2})とやるべき所を grinedit.addVertex("LinearEdge", {"v1": v1, "v2": v2})とやって、 クラスキャスト失敗。 AddVertexの時点で型をチェックするようにしてもいいかもしれない。

GRINEditの中で一番重たい関数は反発力を計算している PL_Repulsion#applyなのだけど、ちょっと眺めて、ループの奥でやっている割り算が 定数での割り算なのであらかじめ逆数を求めて置いて掛け算するようにしたら5%早くなった。 そこで火が付いて、毎回頂点をIMassPointにキャストしてgetPositionしてたのを 先にキャストとgetPositionをすませて配列に入れておくようにしたら元の半分の時間に減った。 あとベクトルの計算を不定長のベクトルと見なしてforで回して計算していたのを、 長さ2のベクトル決めうちにしてインライン展開したら、元の実行時間の7%に縮んだ。 プロファイラ上のもたもたした画面で見ると早くなったのが実感でわかる。 まぁ、プロファイラをかけていることで、関数呼び出しのオーバーヘッドが増えているはずなので、 インライン展開による高速化の度合いは誇張されているだろう。 この高速化のせいで、反発力計算クラスはそのままでは3次元に対応できなくなったけど、 対応させるさほど難しくないし、その見返りとしてプログラム全体で見て30%の高速化になったのだったら 悪くない取引だと思う。

1746頂点の「全ての辺が8本のグラフ」の描画が5FPS以上で動く! 実用的な速度で動かないグラフの例として入れたのに、ぎりぎり実用範囲内に入ってしまった。

物理法則を設計する上で大事なこと。 まず力が連続的に変化すること。 次に作用反作用の法則を入れること。 最後に、現実の物理法則はあり得る物理法則の一つに過ぎないので、 物理学的に正しい物理法則ではなく、得たい結果が得られる物理法則を選ぶべき。 この3つだろうか。 最初の項はちょっと正しくなくて、例えば壁に貼り付く物理法則の場合、 一定距離に近づくと急に力が発生するから連続的ではない。 だから正確に言うと「適切な長さの切り替え区間を挟まずに プラスの力とマイナスの力を切り替えてはいけない」 ということになるだろうか。 要するに「0以上はマイナス1、0未満はプラス1」なんて力は 0周辺で振動を起こすのでダメだということ。 たまに1ピクセル以上の振動を起こすソフトがあるけど、 それは物理演算の設計のミスだろう。 作用反作用がないと合計が0にならずに1方向に動いていってしまう。 例外はやっぱり壁に対する力で、壁は力を吸収しても自然に見える。 最後の物理法則は自由にデザインしてもいいという宣言は重要で、 GRINEditの反発力なんか半径の二乗分の一どころか、半径分の一でもない。 なぜかというと、うっかりこんな実装にしたら、 運悪くすごく近い位置に頂点が並んだが最後、画面の果てのそのまた果てまで吹き飛んでしまう。

プラグインシステムのおかげで新しい頂点や物理法則の実装が楽になったかも。 プラグインフォルダのinit.pyは自動的に発見されて実行されるので、 新しい何かを実装しようと思ったらまずtestフォルダの中にinit.pyを作る。 そしてそこで頂点や辺や物理法則をグラフに追加するコードを書く。 実行すると実装中の頂点とかが表示される。 でJavaのコードを修正して実行して、とやって完成したら、 そのinit.pyをtestFileIconVertex.pyとかに名前変更する。 そうするともう呼び出されなくなるけど、テストフォルダの中に テスト用のスクリプトが入っていることになる。 そのままにしていてもいいし、Jythonでその「新しい頂点」の機能を試すための 簡単なサンプルとしてsampleフォルダに移して置いてもいい。

新しいフローレイアウト用の物理法則を追加。今は強さ決めうちの方向も上下決めうちだけど、手で書いたちっちゃいツリーはちゃんと整形された。明日はもっと大きいツリーや、合流のある例、ループのある例を作ってテストだ。

拡張子を指定するとアイコンを頂点に

iconvertex.png

SWTで拡張子からアイコン画像を取得し。それをAWTのImageに変換して2倍に拡大してから描画しました。ファイルをドラッグドロップしたらこの頂点ができて、ダブルクリックしたらファイルが開く、というのを作りたいのだけど、とりあえずアイコンを描画するところまで。でも残りはさほど難しくない気もする。

問題はマウスハンドラかなぁ。 今は「右ボタンのイベントを処理するハンドラ」「左ボタンのイベントを処理するハンドラ」という二つがあり、そこにMouseOperationクラスのインスタンスを入れる形になっている。でも、逆に言うとその二つしか登録できない。 以前、拡大縮小と平行移動が別のクラスで実装されていて、いちいち切り替えないといけないのが面倒だったので、Shiftキーが押されているかどうかで挙動の変わるものを作ったけど、いまいち納得がいかなかった。それはこういうこと。「右ドラッグ」と「Shiftを押された右ドラッグ」は競合しないものだから、それぞれを取るハンドラを両方同時にアクティブにしてあっても問題は起きない。それなのに「右マウス用ハンドラ」と「左マウス用ハンドラ」の2つしかハンドラを入れる場所がない。現状のまま「ダブルクリック」というドラッグと競合しないイベントを取るハンドラを追加したとしても、また抱き合わせクラスを作るか、さもなくば「ハンドラを切り替えてからダブルクリック」とやるかしかない。これはどう考えてもイベント分配システムの設計が間違っている。

血液型とADHD

僕自身は「血液型で人の性格がわかる」という意見には懐疑的なのですけど、 「血液型が人の性格に関係あるわけないじゃないか!」という意見には否定的です。 たとえて言うならば、琵琶湖に行ってコップ一杯の水を入れたとして、 「水が増えたんだから水面も上がったはずだ!」という意見には 「確かに増えたかも知れないけど観測できるほど水面が上がるかなぁ」と思い、 「琵琶湖の水は膨大だからコップ一杯の水を入れたくらいじゃ増えない!」という意見には 「いや、たとえわずかでも入れた瞬間には確実に増えているだろ」と思う、ということです。

テレビ番組で血液型で何でも決まるような映像を作って流すことが反感を買ったりするようですけど、 それはそのテレビ番組が科学的でないだけです。 「血液型と性格に関連性がある」という仮説を否定する根拠にはなりません。

まぁ、面積670平方キロの琵琶湖に500ccの水を入れたら、 計算上は水面が0.0007ナノメートル上昇するのですが、 どう考えても風で起きた水面の波の方が大きいので観測のしようがありません。

そんなことよりも、遺伝子によって性格が影響される例として、 犬のドーパミンレセプター遺伝子と性格との関係を調べた実験のことをあげようと思い、 検索していたら面白い文章に出くわしました。 くねくね科学探検日記。 単にドーパミンレセプター遺伝子、と覚えていたのですが 「D4DRだったのか!」と目から鱗。 この遺伝子、ADHD(注意欠陥多動性障害, ADHD - Wikipedia)に興味がある人ならご存じかも知れませんが、 ADHDとの関連性が示唆されている遺伝子です。 Wiley InterScience: Journal: Abstract。 リンク先のブログで挙げられている参考文献( Dopamine D4 receptor (D4DR) exon III polymorphism associated with the human personality trait of Novelty Seeking - Nature Genetics)では、 あるコードの繰り返し回数の変異とヒトの新しいものに興味を持つ性格との関連性が示唆されていますが、 ADHDとの関連性を示唆されているのもまさに同じ箇所です。 なんと、そうだったのか!

以前からIT業界にはADHDの人が多いというまことしやかな噂がありましたが、 新しいものに興味を持つ性格とADHDに関連性があるのなら、それって当たり前のことですね。 なるほど。

思うに、最近ADHDや アスペルガー の人が目立つようになってきたのは、別に比率が増えているわけではなく、 出てきやすい社会環境になったからではないでしょうか。 ちょうど、街で車いすの人を見かけることが多くなったけども、 足の不自由な人の割合が増えているわけではないのと同じ。 僕も、今は一応理学博士なわけですけど、半世紀前に生まれていたら 「大学に8年通ったあげく卒業できなかった」とか言ってそうです。 そういう人間にこうやって文章を書いて発表する機会もなかったでしょう。 そう考えるといい時代になったものです。

なんだかAutismSNS 発達障害ソーシャル・ネットワーキング・サイトなんてのもあるみたいです。 完全招待制らしいので誰か誘ってください。

ダメ日記

今日はダメな日。ぐだぐだ。ウェルチのグレープジュース飲んで舌が真っ黒。 肩こりこりこり。集中力が出ない。 かすかに眠いが寝るほどでもなくてどうしよう。 布団に入って何か読もうか。アロマオイルをアロマライトに入れて、電源を入れ忘れる。

今日は久しぶりに鍋。おととい鍋をするつもりで買って、うっかり外食を繰り返して今日。春菊があるのが今までとの違い。いままできれいさっぱり忘れていたけど鍋には春菊を入れないと。ハクサイとネギだけでは緑黄色野菜が足りない。春菊?菊菜?どっちを食べたのかわからない。春菊は冷蔵庫に2日放置すると曲がる。切り口から傷んでそうだったので切り取って捨てた。ハクサイ1/4玉とネギ3本と春菊一袋とエノキ。あと賞味期限が10月25日のソーセージ。ちょうどいいくらいかなぁ。もっと他のものを入れたいので、どこかを削らないといけない。ハクサイもネギも冷凍には弱そうだなぁ…。ハクサイとネギを半分にするのが一番スマートかなぁ。

ラーメンズがMacのCMをしているのでMacを買います。嘘です。 WindowsXPをVMWareに入れるためにきちんと買ったのだけど、 VMWareに入れる方はどうせ「さらの環境」を作ってテストしたりするためのだから、アクティベーションしなくてもいい気がしてきた。必要になったら再インストール。中古で買ったOSの入ってないThinkpadA30にWindows入れちゃおうかなぁ。knoppixを入れてみたけどなぜかハードディスクを認識しなくなったりとか色々ややこしいことになってしまったし。

いらいらすると眉毛が減ってしまう。

あー、もう。 とりあえずマシンを閉じて、それから何をするか考えよう。

2006年11月17日

何回目か忘れた日記

今日は「電車に乗ると生産性がアップする」という仮説の検証のために 東西線を端から端まで往復しています。

北習志野って汚らしいの?(オヤジギャグ)

八千代中央は言いにくい。やちゅょちゅょ。

大体一往復でバッテリーが半減するみたい。(中野~東葉勝田台)。 住んでいる駅が端の方にあるので、 二往復目の途中で駅に着いたときに降りるくらいでちょうどいいかも。


= 2006-11-16 21:55:18 おっと。J2SE 5.0からは可変長引数を取れるのか。 配列を使うしかない、と書いていた。修正修正。

JavaのString#formatとPythonの文字列フォーマットは、 どちらにも相手にない機能がある。orz。 「Javaのformatのことに触れない」という態度は嫌いだけど、 あんまりJavaの説明を書いていると Jythonの本を書いているのかJavaの説明を書いているのかわからなくなってくる。 この件は明確に「JythonとJavaのフォーマット機能の比較」なんでいいんだけど、 気をつけないとただのJavaの説明を書きそうになる。 Javaの拡張for文と可変長引数を組み合わせたら、ほとんどPythonと同じ書き方ができて、 なんだかなぁ、と。


= 2006-11-17 00:11:25 なんか、日記は見せたいのではなくて書きたいのだとわかった。 ローカルで書いて、別に公開しなくてもいいかー、と思ってしまう。

あっ、アップロードする前にブラウザ閉じちゃった。 まぁいっか、明日で…。


= 2006-11-17 00:37:06 びっくりした。Emacsで書いていた大事なファイルが文字化けして読めなくなった。 EUCで開いたら1文字ごとに\222という謎の文字が入っているので、 (replace-string "\222" "") してみたら無事元通りに。なんだったんだろう。

howm日記5日目、かな?

[2006-11-15 13:02] 昨日のEmacsLispでハッシュ状のものから情報を取り出す件、 GNU Emacs Lisp Reference Manual - association (訳注:連想)リスト を参考にして「(assq 'left default-frame-alist)」とやると値が取得できました。 最初は「(assq left default-frame-alist)」と書いてvoid variableと言われ、 次に"left"にしてみてnilと言われ、そうかシンボルにするのかと気づいて三度目の正直。 変数fooが定義されていない状況でも'((foo . bar))と書けるわけですね。
= 2006-11-16 01:15:59 Subversionは便利なんだけど、 うっかりフォルダごと移動したりするとぐちゃぐちゃになってしまうのが困る。 フォルダが移動したことに気がついてくれたりとかすればいいのに。

消して作り直す。


= 2006-11-16 02:11:37 Jythonのコードにツッコミ。CollectionProxy.java
if (object instanceof Vector) {
    return new VectorProxy(((Vector)object));
}
えー。ArrayListのことは無視ですかー。

と思ったらArrayListもちゃんとラップされている。 調べてみたらCollectionProxy2ってクラスがこのメソッドをオーバーライドしてた。

やっぱり読んでると色々つっこみたくなるところがある。 で、パッチを送ろうと思ったら、 やっぱり最新版をチェックアウトしてビルドしてテストできる環境を整えなきゃいけない。

めんどくさい。

でも最新版のコードも読めるようにはしといた方がいいか…。

2006年11月16日

選択範囲の行頭の余計な空白を取り除く

海馬日記 - my-unindent-region――Emacsで「逆インデント」を参考にしつつ、タブとスペースが混在していると使えないので自分用に改造しようと、F1fで関数の意味を調べたり、GNU Emacs Lisp Reference Manualで関数を探したり、見たことのないlet構文やwhile構文を取り除いたりしていたらこんなものができました。

選択範囲を最初にuntabifyしてしまってから、行頭のスペースの数が一番少ないところにあわせてそのスペースを取り去るというもの。最初は「バッファから選択範囲の文字列を取り出して加工して書き戻そう」と思ったのですけど、「選択範囲の文字列を変更」という関数がなんなのかわからなかったのでこうなりました。どうも「編集範囲を制限してからその範囲に処理を行う」というやり方の方がEmacsらしいようです。

(defun my-unindent-region (start end)
  (interactive "r")
  (save-excursion
    (save-restriction
      (narrow-to-region start end)
      (untabify start end)
      (goto-char (point-min))
      (replace-regexp
       (concat "^" 
	       (make-string
		(apply 
		 'min 
		 (mapcar
		  (lambda (line)
		    (progn 
		      (string-match "^ *" line)
		      (match-end 0)))
		  (split-string (buffer-string) "\n")))
		32))
       ""))))

2006年11月15日

Javaでグラフの連結成分を求める

Pythonで書いた findConnectedComponentsの連結成分を求めている部分をJavaに移植したもの。ほぼ同じですね。誰の言葉か忘れたのだけどもJava1.5はLLのようです。 Python版と一番大きく異なるのは型の情報があることで、たとえばPython版では僕の頭の中にしか「componentsは頂点のリストのリスト」という情報がなかったのが、Java版では「Vector<Vector<IVertex>> components」と明記されています。とすると、Java版の方がアルゴリズムの理解のしやすさは上なのかも知れないですね…。むむむ。Pythonでアルゴリズムを書くときもコメントか何かで型を書いておいた方がいいのかなぁ?
// 隣接リストを作る
Hashtable<IVertex, Vector> adjDict = new Hashtable();
for(IVertex v: vertexDict.values()){
    adjDict.put(v, new Vector());
}
for(IEdge e: edgeDict.values()){
    IVertex v1 = e.getV1();
    IVertex v2 = e.getV2();
    adjDict.get(v1).add(v2);
    adjDict.get(v2).add(v1);
}
// 連結成分を求める
Vector<IVertex> visited = new Vector();
Vector<Vector<IVertex>> components = new Vector();
for(IVertex v: vertexDict.values()){
    if(visited.contains(v)){
        continue;
    }
    Vector<IVertex> aComp = new Vector();
    Vector<IVertex> queue = new Vector();
    queue.add(v);
    while(queue.size() > 0){
        Vector<IVertex> newQueue = new Vector();
        for(IVertex current: queue){
            visited.add(current);
            aComp.add(current);
            Vector<IVertex> neighbors = adjDict.get(current);
            for(IVertex neighbor: neighbors){
                if(!visited.contains(neighbor) && !newQueue.contains(neighbor)){
                    newQueue.add(neighbor);
                }
            }
        }
        queue = newQueue;
    }
    components.add(aComp);
}

findConnectedComponents

思いつきで作ってみたので、次回リリース時にサンプルとして添付します。 与えられたグラフの「つながっているグループ」を判別してそれぞれに色をつけるスクリプト。グラフ理論の言葉で言うと連結成分を求めたと言うことになるのかな。

findConnectedComponent.png

69行。

#
# find connected components
#     http://en.wikipedia.org/wiki/Connected_component_(graph_theory)
# グラフの連結成分を求める
#

vs = med.getVertexList()
es = med.getEdgeDict().values()

#
# make adjacency dict

adjDict = {}
for v in vs:
    adjDict[v] = []

for e in es:
    v1 = e.getV1()
    v2 = e.getV2()
    adjDict[v1].append(v2)
    adjDict[v2].append(v1)

#
# find components (Breadth-first search)

visited = []
components = []
for v in med.getVertexList():
    if v in visited: # the vertex was already visited
        continue
    aComp = []
    queue = [v]
    while queue != []:
        newQueue = []
        for current in queue:
            visited.append(current)
            aComp.append(current)
            for neighbor in adjDict[current]:
                if not(neighbor in visited) and not(neighbor in newQueue):
                    newQueue.append(neighbor)
        
        queue = newQueue
    
    components.append(aComp)

def hsv2rgb((h, s, v)):
    hi = int(h / 60) % 6
    f = h / 60.0 - hi
    p = 255 * v * (1.0 - s)
    q = 255 * v * (1.0 - f * s)
    t = 255 * v * (1.0 - (1 - f) * s)
    v *= 255
    return [
        (v, t, p),
        (q, v, p),
        (p, v, t),
        (p, q, v),
        (t, p, v),
        (v, p, q)][hi]

n = len(components)
for i in range(n):
    h = 360.0 / n * i
    rgb = hsv2rgb((h, 0.9, 0.9))
    print rgb
    for v in components[i]:
        v.setBackgroundColor(rgb)

print "ok."

howmで書く日記4日目

[2006-11-14 16:07] 銀行に行った。「印鑑はお持ちですか?」…いいえ。
def bank():
    wait()
    if not(印鑑はお持ちですか):
       return
    (以下略)

= 2006-11-14 16:28:50 秋元@サイボウズラボ・プログラマー・ブログ: 音痴チェッカー。 最初「『ブー』と音が鳴ってドかミか選べといわれる」といった感じのテストをイメージしていたのだけど、 開始するといきなり短い曲が2つ鳴って、同じ物かどうかを答えろといわれる。 それがまた、旋律としてはほとんど同じなんだけど間に余計な音が入っているとか、 和音の一番目立つ音は同じなんだけど、後ろで鳴っている低い音が違うような気もする…、 というものとかでめちゃくちゃ難しい。もう一回聞きたい。

1回目75.0%だったのだけど、もう一度やり直してみて、69.4%に下がった(笑) 疑い出すと全てが微妙に違うように聞こえてくる罠。


= 2006-11-14 19:12:14 「すみか」ってどういう意味だと聞かれて「住む+場所(か)」で、 「ありか」は「ある+か」だと教え、使い方を聞かれたので「宝のありか」を教えたら 「宝の場所」「宝のどころ」はOKなのかと聞き返された。 「ところ」が濁って「どころ」になるという説明はさておき、 「宝の所」だと場所が既知のようなニュアンスがあるのはなぜだろうか。 その理由は日本人の僕にもよくわからない。
= 2006-11-14 19:42:54 なんか頭が痛い…熱っぽい…。
= 2006-11-14 21:00:29 ウノウラボ Unoh Labs: SBO(Social Bookmark Optimization)に関するほにゃらら
ところで、ウノウでは社員を募集していますが、それとは別に僕も素敵な技術系に理解ある彼女を募集しています。

面白い。


= 2006-11-14 21:03:03 そうそう、今日銀行に行ったついでに銀行のそばのダイソーに寄ったんですけど、 マジックテープでケーブルをまとめるのが8本入り100円で売ってました。 輪っかに長い尾っぽが付いた形になっているので、ケーブルをまとめていない状態でも ケーブルから外れてどっかに行ったりしない商品です。 これでUSBから携帯を充電するケーブルをきちんとまとめてカバンに入れておこう。

そうそう、女性はなぜ謎の薬品や不思議な工具を大量に持ち歩いているのに カバンの中がややこしくならないのかについて慎重に考察した結果、 カバンの中にポーチという名の別のカバンが入っているからだとの結論に達しました。 鞄に鞄を入れると爆発して消滅しそうな気がしてしまいますが とりあえず現実世界では爆発しないようなので実践してみることにします。 化粧ポーチじゃなくて筆箱ですけど。


= 2006-11-14 21:25:47 etude_disc_1 - django-ja | Google グループ
アルファじゃないけど好きなBLOGベスト3
・西尾さんのBLOG(本人はアルファーギーク)
ちょっっw

(余計なもの: -1)w


= 2006-11-15 01:26:48 Installing Emacs。 Meadowで起動時に最大化状態で開いて欲しい場合に、 ここで紹介されている手法を使えばよさそう、と思ったら w32-send-sys-commandがvoid-functionだと怒られた。 これによると w32-send-sys-commandはもう捨てられたので使えないということらしい。 リンク先には最大化時の幅と高さを記録して復元する方法が書かれている。 僕の場合はタスクバーが左にあるので位置を(0, 0)にしたのではめり込んでしまう。 (frame-parameters)を評価してleftとtopがいくらになっているかを確認してその値でmodifyする。 ハッシュ状のもの?である(frame-parameters)から特定のキーのものだけ取り出す方法は よくわからなかったので目で探した。

で、.emacsにこれらの値をセットする命令を書き足そうかと思ったら、 すでにそういう情報が書かれているらしき所があったので下のように書き換えた。 無事に最大化状態で開くようになった。

(setq default-frame-alist
      (append (list '(foreground-color . "black")
		    '(background-color . "LemonChiffon")
		    '(background-color . "gray")
		    '(border-color . "black")
		    '(mouse-color . "white")
		    '(cursor-color . "black")
		    '(width . 100)
		    '(height . 40)
		    '(top . -1)
		    '(left . 70))
	      default-frame-alist))

= 2006-11-15 02:17:25 Meadow + gnuserv -- めどうさん で紹介されているgnuservが、どういう方法でMeadowを別プロセスから制御しているのか、 ソースコードを読んでみた。想像以上に短かい。 「(server-eval '(progn 」と「))」で与えられたS式を挟んで 21490番ポートに送っているだけのように見える。 でもPythonでそのポートに接続しようとしたらConnection refusedっていわれちゃった。 うーん。 とりあえずコマンドプロンプトで「 gnudoit "(insert \"hello\")" 」と実行したら開いていたバッファにhelloと書き込まれたので きちんと動作はしているみたいだ。メカニズムをいまいち理解できていない。 21490番のポートにS式を送ったとしても、 それを受け取るのはgnuserv.exeっぽいので、 結局「別プロセスからMeadowへどうやって情報を伝えているのか」 が解決されていない。それがわかればGRINEditから直接たたけるんだけどなぁ。

まぁ、ちょっと歯がゆいけどgnudoit経由でたたくのでもいいかなぁ。

>>> class Meadow:
	def write(self, s):
		gnudoit = r"c:\meadow\gnuserv\gnudoit"
		s = s.replace("\n", r"\n")
		sexp = "(insert \\\"%s\\\")" % s
		cmd = "%s \"%s\"" % (gnudoit, sexp)
		os.system(cmd)

		
>>> m = Meadow()
>>> print >>m, "hello, meadow"

コマンドプロンプトを通るせいで、改行をエスケープしたり二重引用符で囲んだり ちょっと面倒だったけども、そこをちゃんとしたらちゃんと書き込まれる。

2006年11月14日

howmで書く日記3日目

スラッシュドット ジャパン | 12月23日、東北大で 「理系白書シンポジウムin仙台」開催
クリスマス・イヴイヴ(?)にエンジェルたちと素敵な時間を過ごしてみてはいかがでしょうか
うはー。ぜひ行きたい。

冗談はさておき、科学をやっている女性が少ないという考え方にはちょっと疑問を感じる。 そもそも科学とは何なのかと。今メジャーな科学の分野っていうのは、 かつて男性が興味を持ち発展させてきた分野だ。 だから、その分野に興味を持つ女性が、男性より少なくても、それは何もおかしくないのでは。

以前近くでやっていたので参加した 日本顔学会 のフォーラムでは、資生堂や花王の女性研究員がたくさんいた。 しかし、例えば高校生が、こういう研究をやってみたいと思った場合に、 いったいどの学部に入ればいいのか?工学?生物学?心理学?

仮説を立て、 ある程度の再現性のある実験を行い、 ある程度客観的な観察を行って、 仮説の正しさを確認する。これって科学? それならば、料理研究家がやっていることは科学じゃないのか?

料理には生成した薬品も使わないし、でかい計測機器も使わないので 「科学っぽさ」がない。それって単に 「今までの(男性主導で進められてきた)科学に似ていない」 というだけではないだろうか。

「計測機器を使わずに舌を使うのが科学的でない」という主張も 「今までのメジャーな科学に似ていない」というだけ。 また例えば錯視の研究は計測機器ではなく人間の視覚を使うので、 計測機器を使わない研究が科学的でないという主張はおかしい。

「実験が必ずしも再現しないから科学的でない」という主張もおかしい。 そもそも高い再現性があるのは科学のごく一分野に過ぎないわけで、 生物学でも実験経済学でも再現性は100%ではない。 それは実験の前提条件を管理しやすいかどうかの違いでしかない。

僕は、「科学」は、 今「科学」と呼ばれているものよりも はるかに広いものだと思っているようだ。


= 2006-11-13 17:06:41 Meadow のフォント設定 -- めどうさん を参考にしてフォントサイズを大きくした。 Heightを16にしても全然大きくならないと思ったら、 16ポイントじゃなくて16ピクセルだった。 20と指定したら、16ポイントくらいの大きさになった。 しかしime-fontの設定をそこに書かれているとおりにすると wrong type argument listpといわれてしまう。 試しに"private-fontset-japanese-jisx0208"の代わりに '("private-fontset-japanese-jisx0208")と書いてみたら 論理フォントとして適切じゃないというエラー。 よくわからないので保留にしよう。
= 2006-11-13 21:31:12 今日覚えたキーバインド。 C-xoで別のバッファにうつる。C-xhで全選択 (マウスでやった時みたいに色が付かないけどMark setと表示される) M-wでコピー。C-hbでキーバインドの一覧が出る。

覚えていたキーバインド。C-x1で一画面表示に。C-xkでバッファを閉じる。 C-xbでバッファを変える。

以前「足踏みシフトキーがあると生産性が上がるのでは」と考えていたけど Meadowを使い始めてから「足踏みC-cキー」が欲しくなってきた。


= 2006-11-13 22:38:18 フォントの設定 - Meadow - Trac。 ここに書かれている方法を試したらIMEの変換中の文字と確定後の文字が同じになった。 よかった、よかった、といおうとしたら英文字だけCourierだからまだダメ。

結局自分で書いた設定を全部捨てて全面的にリンク先の設定に変えました。 あとフォントサイズを18に変更。

Emacsはほとんどの操作がEmacsLispの関数を呼び出すことで実現できるのですばらしい。 最初にそういう設計をするときには関数呼び出しのオーバーヘッドとか気にしてしまいそうだが、 速度の問題は時間とともに勝手に解決するのに対し、 設計の問題は時間とともに勝手に悪化する(ことが多い)ので、 やっぱりこうあるべきなのかも知れない。

で、GRINEditのローカルでの操作もXML-RPCと同じCommonGatewayクラスを通して行うことにすれば、 操作の共有とか複数人同時編集とかができそうな気がする。 デメリットはもちろん一人で使っているときのオーバーヘッドだが…

いいよね。律速段階は物理演算なんだから。オーバーヘッドのことは無視無視。

あー。別に自分自身にXMLでクエリを投げろといっているわけではないから、さほど問題ではなさそう。 問題なのはネットワーク共有した場合で、 これはネットワークが間に挟まるから人間が知覚できる遅延が起こりうる。 やっぱりここは非同期にするしか。 パラレルワールド化が怖いなぁ。

2006年11月13日

BufferStrategy

[2006-11-13 21:24] J2SE, v1.4 の新機能 Buffer Strategyを使えば高速に描画できるようだ。 しかし現状で100頂点のグラフが60FPSで動いているし、 描画の切り替えは律速ではない。 遅いのは反発力の計算なので、高速化がしたいならば空間分割とかをする方がいいのかも知れない。

新しい頂点クラスを作る手順メモ

[2006-11-13 18:25] まずpluginsの中にtestというフォルダを作ってinit.pyを作成。
grinedit.addVertex("BoxVertex", {})
と書いてみる。実行すると頂点が表示された。OK。

BoxVertexの所を org.nishiohirokazu.graph.FileVertex に変えてみる。 Graph#addObjでキャストエラー。IGRINObjectインターフェイスをimplementsしていないから。 ちなみに今回はRenderableVertexを継承していないのだ。 なぜならextends JLabelだから。

	private String id;
	public String getId() {
		return id;
	}

	public void setId(Object o){
		id = o.toString();
	}

	public Hashtable getParams() {
		return new Hashtable();
	}

SimpleLayout#layoutStepでキャストエラー。 MassPointを継承していないから。これはIMassPointに変えるべきですな。 IMassPointをimplementsしてMassPointを参考に実装。

	private Vector dVelList = new Vector();
	private double[] position = new double[2];
	private double[] velocity = new double[2];

	public Vector getDVelList() {
		return dVelList;
	}

	public void setDVelList(Vector velList) {
		dVelList = velList;
	}

	public double[] getPosition() {
		return position;
	}

	public void setPosition(double[] position) {
		this.position = position;
	}

	public double[] getVelocity() {
		return velocity;
	}

	public void setVelocity(double[] velocity) {
		this.velocity = velocity;
	}

PL_RepulsionでRenderableVertexにキャストしようとしてエラー。 これはRepulsionが悪い。 IMassPointに変更。

ワールド座標系からスクリーン座標系に変換するところで RenderableVertexにキャストしていたのを、

Object o = i.next();
IMassPoint v = (IMassPoint) o;
IHasScreenPos sv = (IHasScreenPos) o;
sv.setScreenPos(vp.viewportTransform(v.getPosition()));
に修正。IHasScreenPosにセッタがなかったので追加。
private double[] screenPos;
public double[] getScreenPos() {
	return screenPos;
}
public void setScreenPos(double[] pos) {
	screenPos = pos;
}

レンダリングエンジンがIRenderにキャストしようとするのでそれもimplements

public void render(Object target) {
	update((Graphics) target);
}
無事描画はされるようになったが、描画される位置がおかしい。 どうやって直すかなぁ、これ。

legacyFormatの短いサンプル

VERTEX
3
1	Hello
2	GRINEdit
EDGE
1	2
2	3

legacyFormatは簡単なグラフを作る上では楽に書けるので、 今後のバージョンでも(非推奨ながら)残していこうと思っています。 しかし、頂点の色など色々とカスタマイズをしようとすると、 タブ区切りの現状ではどんどん泥沼にはまっていきます。 それを解決するためにYAMLベースで作った新しいフォーマットが 今後のリリースでは「標準のフォーマット」という位置づけになる予定です。

Vertex: 
  v1: {label: Hello}
  v2: {label: GRINEdit}
  v3: {}
Edge: 
  e1: [v1, v2]
  e2: [v2, v3]

眠たい日記

[2006-11-12 07:28] howmで書いてから貼る日記、第二弾。

土曜日の朝4時に、そろそろ眠いから寝ようと思って布団に入ったものの、 眠れなかった。体と脳のリズムが一致していないと、疲れて眠りたいのに 眠れなくて困る。こういうときに「睡眠改善薬ドリエル♪」とか飲めばいいのかなぁ。

【よい睡眠をとるために】 睡眠障害の診断・治療ガイドラインを読んでみたが、やっぱり「同じ時間に毎日起床」を守っていないのがいけないのだろう。

脳よりも先に体が疲れてしまう原因をなくすのも重要かもしれない。 まず作業に没頭しすぎて食事を取らないのはよくない。 ある限界を超えると急に肩こりや頭痛になって出てくる。 冷えも要注意だが、暖房による乾燥も目によくない。 昨日のは空気が乾燥して目が脳より先にダウンしたのかもしれない。

杜仲茶の有効成分が熱に強いのを利用して、杜仲茶を濃く出しつつ加湿器代わりにしてみる。

リズムが崩れて変なことになったせいで、昨日は18時に起きて、そして今朝だけど眠い。ここで寝ると手がつけられなくなるので、頑張って起きておいて、早めに寝て、明日も早起きしよう。そうしよう。


__ = [2006-11-12 17:11] ダメだった(´・ω・`) 遅めの朝ご飯を10時頃に食べたら眠くなって、眠気覚ましにゲームを始めたら退屈な展開になってなおさら眠くなって、途中でやめて30分だけ寝ることにして、目覚ましをかけて寝て、一瞬で30分経って驚いて、もう30分寝て、もう30分寝て、もう一度寝て、起きたら17時。

時間帯的に朝ご飯のはずなのにたくさん食べ過ぎたのが眠くなった原因か。胃がいっぱいだったので当初の予定だった「自転車でららぽーとへ」ができなかった。あと、何よりも根源的な問題は意志の弱さかも知れない。滝に打たれると意志が強くなったりするんだろうか?

まだ5時なのでまにあう。自転車で買い物に行ってこよう。 ラベンダーのエッセンシャルオイルを買ってきて寝る前につけることにしよう。


__ = [2006-11-12 20:15] ささださんとこから。 第1回 UEC コンピュータ 大貧民大会。じゃんけん大会より面白そう。


__ = [2006-11-13 00:40] Javaでファイル名からそのファイルのアイコンを取得するのは、 思ったより難しそう。com.ms.win32.SHFILEINFOを使って ファイルに関連付けられたアイコンを取得するには?[2.0のみ、C#、VB] - @IT で紹介されているAPIを叩けば可能だと思うけど、これは WFC (Windows Foundation Classes for Java)っていうMSのJavaVMでしか動かない ライブラリの中にあるらしい。

しばらく調べてダメだったら「外部ファイルへのリンク」を表現するマークと拡張子の組み合わせで行くしかないかなぁ。


__ = [2006-11-13 01:03] GNU Emacs Lispリファレンスマニュアル: Emacs Lisp関数のアドバイス。 おー、ドキュメント文字列っぽいものがあるみたい。しかもアスペクト指向?!

GNU Emacs Lispリファレンスマニュアル: Coding Conventions 「C-c letter」はユーザ向けに予約されており、他にもメジャーモード用、マイナーモード用の割り当てもあるんだそうな。

とりあえず(replace-string "foo" "bar")で置換できるとか (insert "foo")で挿入できるとかがわかった。 これらの関数はみんなカレントバッファや 現在のポイントに対して処理を行うようだ。 目的を果たすにはまずバッファをコピーしてから置換する必要があるのかなぁ。 でも、よく考えると、今までブラウザで書いていたときはsplitボタンで <split><p><a name="040358" href="http://www.nishiohirokazu.org/blog/2006/11/howm.html#040358">__</a> 等という文字列が挿入されるようになっていたわけなので、 howmで書いたのを置換するまでもなく、両方で有効な書き方で挿入すればいいだけじゃないかと。 ローカルのhowmの文章に多少タグが混じろうと、読むのは自分だけなんだから別に問題ないし。

じゃあaction-lock.elの105行目あたりにあるaction-lock-dateあたりを参考に

(insert
 (format-time-string
  "<split><a name='%H%M%S' href='#%H%M%S'>\n= %Y-%m-%d %H:%M:%S\n</a>"))
って感じで。

知らない構文がいくつか。,とか&とか@とか。

あとはこれをなんかのキーに割り当てる方法を調べよう。 howm-mode.elの300行目にあるhowm-set-keymapの中で、 define-keyという関数が呼ばれているのでこれを使うみたいだけど、 使い方がわかりにくいなぁ。

(defun mylib-insert-split ()
  (insert
   (format-time-string
    "<split><a name='%H%M%S' href='#%H%M%S'>\n= %Y-%m-%d %H:%M:%S\n</a>")))

(define-key global-map "\C-cs" 'mylib-insert-split)
と書いたら C-c sとタイプしたときにWrong type argument commandpといわれてしまう。

interactive - refwiki こういうのに使う関数は、 ただの関数じゃなくて(interactive)と宣言しないと行けないらしい。 これ、見かけ上は関数の中で別の関数を呼んでるだけに見えるけど、 挙動から考えると関数オブジェクトに何らかの属性をつけているように思える。 マクロでなんかするのだろうか。謎が多い。

でもとりあえず使えるようになったからいいとしよう。 マウスを使わない分、もとのよりいいかも。 Meadowはこうやって簡単に自分用のカスタマイズができることを考えると便利。 viも慣れるとPythonでカスタマイズできて便利なのかも知れないけど、 viと違ってEmacs Lispは「腐った言語」じゃないし、 オムニ補完よりオリジナルのhowmの方を使いたいので、 とりあえずはMeadowでいいや。

サクラエディタをアンインストールしてもいいと思えるまでには、 あとgrepの使い方を調べないとな。


= 2006-11-13 02:47:42 今日はラベンダーのエッセンシャルオイルを買いに行ったのだけど、 ピュアなのをかいでみて、いまいちピンと来なかったので 「眠り姫」というブレンドものを買ってきました。

2006年11月11日

howmで書いてからアップする日記

howm: Hitori Otegaru Wiki Modokiで書いています。

まぁ、もともと「一日一つエントリーを作って、そこにだらだらHTMLで書き足していく」という編集スタイルだったので、Firefox上のtextareaの代わりにMeadowが使われるだけ。投稿時に「貼り付けて保存」というワンステップが余計にかかるけど本質的な問題ではないし、記事がリアルタイムに公開されないけど別にイベントの中継をやっているわけではないから支障はなかろう。

将来的には特定の文字列(例えば「{ブログに公開}」が含まれているものが自動的に公開されるとかにしてもいいかもしれない。

C-x,dで日にちが入るので、C-x,tで時刻が入るのかと思いきや入らない。

C-x bでバッファを切り替えようと思ったけども、 ファイル名が日時なのでどれが目的のものかわからない。C-c,.で一覧を出して選んだ。

今のMovableTypeで日記を書く際には、編集画面につけた「split」ボタンで区切りの線とアンカータグを追加している。howmでは一つのメモの中にいくつも書く場合はタイトルを表す「= 」で区切るみたい。{_}と書いて1文字戻ってEnterを押すと[2006-11-10 20:19]というように日時が挿入される。これが最良の方法かどうかはわからないけども、とりあえず「= [日時]」という形で区切りを入れることにする。自動アップロードする場合にはこれを区切り線とアンカーに変換しないと行けないなぁ。


_= [2006-11-10 20:16] _ 「三月の甘納豆のうふふふふ」や 「たんぽぽの ぽぽの あたりが  火事ですよ」などと言った俳句が面白い坪内稔典 - Wikipedia氏の俳書展が四谷で17日まで開かれているようです。haiten


_= [2006-11-10 20:33]_ 土星の南極に巨大な目を持った台風のような渦巻きが発見された件について。 NASA - NASA Sees into the Eye of a Monster Storm on Saturn。動画もあります。 おそらく渦の中心には電波望遠鏡があって、ガスでできた土星人が渦の下から外部の星と通信しているんですよ。灯台もと暗し。残念なことにガスの関係で極にしか望遠鏡を設置できず、地球が出している電波は赤道方向から来るので分厚いガスに阻まれて受信することができないわけです。土星人もSETIみたいなのをやっているんだけど、やっぱり残念ながら南極方向にだけ電波を出すので地球には届かない。土星人たちはガスのせいで周りを観測できないので、自分たちが太陽系の一員であることすら知らないのです。外に出ればわかるんだろうけどね、土星は質量が大きいので軌道に上がるだけで大変です。きっと軌道エレベータが開発されるまで無理でしょう。もっともダイヤモンドは豊富にありそうですが。


_= [2006-11-10 21:10] _Genbankを使うことがまたあるとは思わなかった。 うーん。 読者のほとんどはバイオインフォマティクスには興味がないのだから、 正確さを期して詳しい説明をするより、 多少嘘でもすんなり流した方がいいのかもなぁ。 FASTA形式を使えば済む所でGenbank形式のデータを使って、 「このフォーマットを読み込むパーサを自分で書くよりも、 すでにあるものを使った方が、 間違いも入りにくいしよっぽど確実です」 というほうが必要性がわかりやすい。

実際問題として、先に進むとFASTAじゃダメなケースも出てくるわけだし。 紙面が限られているからそういうケースにまで話を広げられないだけだし。


__ ふう。暖房つけると目が乾く。

チロルチョコのきなこもち味はきなこもち味だった。どのあたりがチョコかがよくわからない。真ん中の謎のゲルが何でできているのかが気になる。中のゲルだけ食べてみたい。


_= [2006-11-11 02:20] _ http://www.asahi-net.or.jp/~pw9s-szk/emacs/elisp_net.html EmacsLispでHTTPクライアントを作っているサンプルコードがある。18行。

バッファの中身を取得して適当に置換してMovableTypeのAPIをHTTPで叩いてやれば howmとMovableTypeの連携はさほど難しくなさそう。


__ No.0097 ロード画面の表示1。 すごい、日本語だ。 Java:Swing:JLabel:文字と画像の両方を表示する場合。 画像を表示させるのは簡単。ProcessBuilder (Java 2 Platform SE 5.0)。子プロセスの起動の仕方。

外部のJarファイルをたくさん使っているJavaのプログラムは、初回起動時にそのJarファイルを処理するために時間がかかる。GRINEditの場合、10秒くらいかかる。その間に「あれ?」と言ってもう一度起動してみようとする人が出てしまう。そこでスプラッシュ画面を出そうと思ったのだけど、当然のことながらプログラムが起動される前のJarファイルの処理で時間がかかっているのだから、同じプログラムにしても意味がない。というわけでスプラッシュ画面を出してGRINEditを起動するプログラムを作った。ただ画面を出すだけにしておけばいいものを、進んでいるのがわかるようにGRINEditの出力をスプラッシュ側に出そうとしたのでちょっと難しかったようだ。

これGRINEdit本体との独立性が高いから、つまづこうがこけようが実害がないということで、ITスクールで知り合った子に任せてたのだけど、時間が取れないとのことでキャンセルされてしまったのだ。で、仕方なく自分でやっていたというわけ。2時間かからなかったが…。これを9月の末に「10月末までに作れる?完成したら報酬1万円でいい?」って言うのはそんなに無茶な話ではなかったと思いたい。僕もProcessBuilderとか知らなかったけどググったらすぐにわかることだしなぁ。そんなに難しかったかなぁ。

あー。「もしエラー終了したらエラーメッセージをコピペ出来るような感じ」って仕様、まだ実装してないや。もう28時半なので明日作ろう。

2006年11月09日

メール捨てられてる?日記

Gmailがメールを捨てている - ただのにっき (2006-11-07)。ちょうど昨日、IPAから「メールで送ったのに返事がない」と紙メールが来て、検索してみたけども見つからないからおかしいなぁと言っていたところ。捨てられたのだろうか?

メールが必ず配達されるとは限らないということを忘れないようにしないといけない。IPAからの紙メールは配達証明郵便で来ました。きちんと配達されたことを確認したい場合は配達証明郵便しかないんでしょうかね。


__ Googleカレンダー、使ってみようとしているのだけどやっぱりよくわからない。12/23 13:00-12/27 15:00と書いて保存しても12/23 13:00-12/23 14:00のまま。「保存されました」と表示されているのに。複数日の用事はいちいち複数個書かないと行けないのだろうか?


__ ノートパソコンを持って移動した際にACアダプタを忘れる問題と、ミュートし忘れたままサスペンドしてレジューム時に音が鳴ってしまう問題を同時に解決する方法を思いついた。

先にACアダプタを抜いてカバンにしまえばいいんだ。先にパソコンをしまうからしまい終わった時点で全部終わった気になってACアダプタを忘れる。 先にACアダプタを抜けば、ミュートになっていなければ音が鳴るので気がつく。ACアダプタを抜いて、それを手に持ったままパソコンをミュートしてハイバネーションさせて、待っている間にACアダプタのケーブルをまとめてカバンにしまい、ハイバネーションが終わったパソコンをカバンにしまう。これでばっちり。


__ 読みやすいバイナリ時計 - Engadget Japanese

そもそも2進法なのに部分的に60進法とか許せない。1分を64秒にしよう。1時間は64分。そうすると1日が21.09375時間になるなぁ…。微妙。いっそ一日を32時間にしよう。それにあわせて秒の方を縮ませる。そうすると大体今の1秒が1.5秒になる。新しい時分秒を仮にbih, bim, bisと書くことにすると、1秒は1.51bis、1分は1.42bim、1時間は1.33bih。アナログ時計の文字盤には歴史ある六十四卦 - Wikipediaを使用。 こんな感じ 時針は2日で1周。

先天図 - Wikipediaの方が詳しい。

「アジアな感じが受けてアメリカで馬鹿売れ」とかにならないかなぁ。

>>> def toBin(v):
	result = ""
	for i in range(6):
		result = str(v % 2) + result
		v /= 2
	return result

>>> def binaryTime():
	from time import localtime
	t = localtime()
	t = (t[3] * 60 + t[5]) * 60 + t[5]
	SEC_PER_DAY = 60 * 60 * 24
	t = float(t % SEC_PER_DAY) / SEC_PER_DAY
	t *= 32
	bih = int(t)
	t -= bih
	t *= 64
	bim = int(t)
	t -= bim
	t *= 64
	bis = int(t)
	print "%s°%s′%s″" % tuple(map(toBin, (bih, bim, bis)))

	
>>> binaryTime()
010110°000111′111100″

こんな感じ。下が上位ビットで、陽が1、陰が0なので 分が地天泰で秒が雷天大壮ですね。


__ 「給与所得者の扶養控除等申告書」の居所の欄、今回もらったものには小さい字で「H19.1.1現在の住民登録住所を記載してください」と書いてある。

保険の控除とか色々書いてあるけど、僕は今保険のない状態なので提出しないでよさそう。扶養控除等申告書に名前を書いて判子を押すだけ。

あー。角2の封筒がないや。家にあったような気もするし、この前使い切ったような気もする。うーん。どっちみちもう郵便局が開いていないから、今日帰って確認して明日出せばいいんだけど。

スティックのりもカバンに入れよう。ノリがないと何かと不便だ。


__ やっぱりGmailやめようかなぁ。


__ 手帳のメモを見て「キムラ」って誰のことだろう、としばらく悩んだが「払う」だった。


__ 削除や名前変更ができないフォルダやファイルができた場合の対処法。

hxxk.jp - 「ほかの人またはプログラムによって使用されています。ファイルを使用している可能性があるプログラムをすべて閉じてから、やり直してください。」

それでもダメだったら、タスクマネージャから explorer.exe のプロセスを殺して、「ファイル (F) 」→「新しいタスクの実行 (N) 」から explorer.exe を再起動

おおおお、名前変更できた! explorerを殺しても大丈夫だというのは目から鱗。ログイン前の画面に戻りそうに思ったのだけどそうではないみたい。


__ KNOPPIX。 中古で2万円ちょいで買ってきたThinkpadA30に、KNOPPIXのイメージを焼いたCDを入れて起動したらそれだけで簡単にブラウザとか使えるようになって便利な時代になったものだと感動していました。が、ディスク音がうるさい。CDだもん。あとホームディレクトリをメモリ上に取っているので、何かをインストールしても再起動すると消えてしまいます。そこでせっかく20GBもハードディスクがあるのでこれを使おうかと。

/usr/sbin/knoppix-installerを実行するだけでいいような雰囲気だったのでとりあえず実行してみたところ、ハードディスクのパーティションを変更するので中身が消えますとの警告が。一応ハードディスクの中には中古パソコン屋の人が入れておいてくれた最小限の?ファイルが入っているのでせっかくだからバックアップを取ることに。「使うかどうかわからないけどとりあえず捨てない」という選択をするから部屋とか片付かないんだけどなぁ。

試しにUSBの外付けHDDをつないでみると、普通に認識してアイコンが現れる。なんて便利なんだ!しかしなぜか読み出し専用になっていてファイルが書き込めない。謎。

結局ネットワーク上のHDDにsmb://10.xxx.xxx.xxxなどとアクセスしたところ、問題なく書き込めたのでそれでいいことにしました。

インストールは柿1個食べ終わる前にあっさり終わってしまいました。 パーティションを切るのなんか、テンプレートが用意されていて選ぶだけでOK。ただ、HDDをマウントしたままだったので2回失敗しました。 そして、インストール自体はあっさり終わったのだけど「ブートディスクを作成しますか?フロッピーを入れてください」と言われてフロッピーがなかったのでNOを選んでしまったら、再起動してもMissing Operating Systemと表示されて起動しませんorz

まぁ、CDを入れれば今まで通り使えるので当分はそれで行くことにします。 今度実家に帰ったときにフロッピー持ってこよう。

とりあえず@IT:KNOPPIXでディスク上にホームディレクトリを作成するにはを試す。

以前は大きいファイルを扱うとCDが最高速で回りっぱなしの状態が1時間以上続いて耳によくなかったけど、ならなくなった。

WMVが見れないので@IT:Windows Media Player用の動画ファイルを再生するにはで書かれているwin32codecsを入れる。

ダウンロードに時間がかかるので待っている間にメインマシンにMeadowを入れる。howm-mode.vimは、本家とはちょっと挙動が違うらしいし、Pythonで書かれていないので、それだったら本家のEmacsLispののほうがまだ読みやすいだろう、という発想。

meadowをインストールした後、どこがホームディレクトリになるのか少し悩む。c:\meadowにインストールした場合、c:\meadowがホームディレクトリで、dot.emacsというファイルがあるのでこれを.emacsにリネームすればいいみたい。このフォルダの下にhowmというフォルダを作ってそこへhowmのスクリプトなどをコピー…してはいけない。なぜならデータを保存する~/howmとかぶってしまい、何のエラーメッセージも出さずにスクリプトがメモとして検索されるようになる&メニューが壊れる。何も登録する前から、ドキュメントの中の記述を拾ってしまって「ハイウェイ銀河」などがたくさん登録されてしまう。

使ってみた。便利。 細かいお役立ち機能(C-c , dで23と打ってEnterすると今月の23日の日付が入るとか)が色々あるので、自前で実装する気はなくなった。どうすればhowmとGRINEditをストレスなくシームレスにつなぐか。

Pythonの「>>> 」と衝突するのではないか、という懸念は、確かに衝突するのでさっさと変更。howm-mode.elの52行目あたりに(defvar howm-ref-header ">>>" "Header string for explicit link.")というのがあるので、"=>"に変えた。

将来の自分の検索しやすさを考えるとこういう日記もここじゃなくてhowmでつけた方がいいのかも知れないが…。

2006年11月08日

頭痛い日記

省エネのために、昼休みは消灯することにし、それでは暗いので希望者全員に電気スタンドを支給する…節約されたエネルギーより電気スタンドを作るのに必要なエネルギーの方が多い気が。


__ 頭が痛くてちょっと吐き気が。

きちんと食事をしないからだ。 あと眼精疲労。

2006年11月07日

寒い日記

寒い!寒いよ!

毎日「日記」というタイトルがただ続いているとなんかタイトル一覧が面白くないので少しずつ変えることにしました。


__ www.textfile.org - 音を鳴らすプログラム言語

A音を鳴らすのが「Hello World」なら、無限音階(Shepard Tone)はさしずめ「ハノイの塔」。

個人的には、無限音階はただの「while True」だと思いますが…。

3本の棒をドミソに対応させ、1本目から2本目に移動させるときには「ドミ」、逆に移動させるときには「ミド」と鳴らすようにすると、点対称な楽譜ができますね。


__

YAMLベースの新しいフォーマット

beta2.0で標準のフォーマットとして位置づける予定のYAMLベースの新しいフォーマットが一応できました。

GRINEditの中の頂点・辺・物理演算などのオブジェクト(以下GRINEditオブジェクト)はIGRINEditインターフェイスをimplementsすることになっています。このインターフェイスではgetIDというStringを返すメソッドが宣言されています。GRINEditオブジェクトはXML-RPCやYAMLなどの参照(ポインタ)を直接扱えない方法で操作できるように、一意なID文字列を持っています。med.getObject(ID)でそのID文字列からオブジェクトを取得できます。

またGRINEditオブジェクトは、そのIDをキーとするハッシュで管理されています。そのハッシュ自体も文字列をキーとするハッシュ(以下namedDict)で管理されています。例えば"Vertex"というキーに対応するハッシュには、各頂点がID文字列をキーとして入っています。この大元のHashtableはGraphのnamedDictionariesというフィールドに入っています。

基本的には、このnamedDictionariesをシリアライズすればよいのですが、プラグインなどでユーザが任意のクラスをつっこむ関係上、それぞれのオブジェクトがどういうクラスなのかは不特定です。そこで全てのGRINEditオブジェクトをclassnameとparamsという二つのキーを持つハッシュによって表現します。IGRINEditインターフェイスはgetParamsというメソッドも宣言しているので、全てのGRINEditオブジェクトはgetParamsメソッドを持つことになります。XML-RPC経由でオブジェクトを作成する際にはクラス名とパラメータを与えますが、YAMLで保存されたデータもそのルーチンを利用しています。

YAMLで保存したデータをここに載せようかと思ったのですけど、長いので末尾に。2つの頂点を1本の辺でつないであるシンプルなグラフでも、単純にgtParamsの内容で保存すると、全ての属性を保存してしまうので長くなります。そこで、他のソフトウェアなどから出力する際に楽なようにいくつか省略ルールを追加しました。

  • namedDict"Law"は丸ごと省略できる。省略した際はデフォルトの「頂点が反発」「辺がバネ」「アンカー」の3つが指定される。
  • 頂点のクラスがBoxVertexの場合、classnameを省略できる。頂点オブジェクトがキー"classname"を持たない場合、そのハッシュがparamsであると判断される
  • 辺のクラスがLinearEdgeの場合、classnameを省略できる。辺オブジェクトがキー"classname"を持たない場合、paramsであると判断される
  • 辺のparamsがハッシュでない場合、{"v1": params[0], "v2": params[1]}と指定されたものと見なす
  • paramsのうち、idの値は指定されていようがいまいが、namedDictのキーの値が用いられる
この一連の省略記法を使うことで、2頂点のグラフはこう書けます。
Vertex: 
  v1: 
    label: Hello
  v2: 
    label: GRINEdit
Edge: 
  e1: [v1, v2]
ここでは頂点にラベルを指定していますが、それも必要ない場合は以下のようになります。
Vertex: 
  v1: {}
  v2: {}
Edge: 
  e1: [v1, v2]
以下、機械的に出力したYAML。
--- 
Law: 
  Anchor: 
    classname: org.nishiohirokazu.layout.PL_Anchor
    params: 
      target: 
      id: Anchor
  Repulsion: 
    classname: org.nishiohirokazu.layout.PL_Repulsion
    params: 
      repulsionK: !java.lang.Double 0.02
      repulsionRadius: !java.lang.Double 3.0
      id: Repulsion
  SpringEdge: 
    classname: org.nishiohirokazu.layout.PL_SpringEdge
    params: 
      defaultSpringStrength: !java.lang.Double 0.1
      defaultNormalLength: !java.lang.Double 1.0
      id: SpringEdge
version: alpha0.20
Edge: 
  e1: 
    classname: org.nishiohirokazu.graph.LinearEdge
    params: 
      color: 
        - 0
        - 0
        - 0
      v2: v2
      id: e1
      v1: v1
Vertex: 
  v2: 
    classname: org.nishiohirokazu.graph.BoxVertex
    params: 
      id: v2
      velocity: 
        - !java.lang.Double 0.0
        - !java.lang.Double 0.0
      bound: 
        - 57
        - 22
      selfLink: &1 false
      position: 
        - !java.lang.Double -0.8146433605417978
        - !java.lang.Double 0.36293197932640203
      letterColor: 
        - 0
        - 0
        - 0
      label: GRINEdit
      frameColor: 
        - 0
        - 0
        - 0
      bgcolor: 
        - 100
        - 200
        - 100
  v1: 
    classname: org.nishiohirokazu.graph.BoxVertex
    params: 
      id: v1
      velocity: 
        - !java.lang.Double 6.938893903907228E-18
        - !java.lang.Double 0.0
      bound: 
        - 35
        - 22
      selfLink: *1
      position: 
        - !java.lang.Double 0.0381343095012234
        - !java.lang.Double -0.43752799872355813
      letterColor: 
        - 0
        - 0
        - 0
      label: Hello
      frameColor: 
        - 0
        - 0
        - 0
      bgcolor: 
        - 100
        - 200
        - 100

2006年11月06日

Re: Re: Pythonのジェネレータで四角いらせんを書いた

逃走航路@hatena - Re:Pythonのジェネレータで四角いらせんを書いた:西尾泰和のブログにお返事。 元の記事が「アルゴリズムを確認するためにPythonでわかりやすく書いてからJavaで書く」という趣旨であることをはおいといて、やっぱりよく似たフレーズが4回も繰り返してあるとまとめたくなるのはプログラマの性ですよね。僕なら同じ手続きは以下のように関数にまとめて、
>>> def squareSpiral():
	width = 0
	p = (0, 0)
	yield p
	ops = [
		lambda (x, y), d: (x + d, y),
		lambda (x, y), d: (x, y + d)
	]
	while True:
		width += 1
		for i in range(width):
			p = ops[0](p, 1)
			yield p
		for i in range(width):
			p = ops[1](p, 1)
			yield p
		width += 1
		for i in range(width):
			p = ops[0](p, -1)
			yield p
		for i in range(width):
			p = ops[1](p, -1)
			yield p
その関数を順番に使っている部分はforにまとめ、
>>> def squareSpiral():
	width = 0
	p = (0, 0)
	yield p
	ops = [
		lambda (x, y), d: (x + d, y),
		lambda (x, y), d: (x, y + d)
	]
	while True:
		width += 1
		for op in ops:
			for i in range(width):
				p = op(p, 1)
				yield p

		width += 1
		for op in ops:
			for i in range(width):
				p = op(p, -1)
				yield p
関数の引数が異なるだけの部分もforでまとめます。
>>> def squareSpiral():
	width = 0
	p = (0, 0)
	yield p
	ops = [
		lambda (x, y), d: (x + d, y),
		lambda (x, y), d: (x, y + d)
	]
	while True:
		for d in [1, -1]:
			width += 1
			for op in ops:
				for i in range(width):
					p = op(p, d)
					yield p
あ、でも縮んでない…。 縮ませるためにはやっぱり破壊的メソッドを使って代入を消しておいて、
>>> def squareSpiral():
	width = 0
	p = [0, 0]
	yield tuple(p)
	ops = [
		lambda p, d: p.__setitem__(0, p[0] + d) or p,
		lambda p, d: p.__setitem__(1, p[1] + d) or p
	]
	while True:
		for d in [1, -1]:
			width += 1
			for op in ops:
				for i in range(width):
					yield tuple(op(p, d))
最後に残った重複(ops)もforでまとめる。
def squareSpiral():
  width = 0
  p = [0, 0]
  yield tuple(p)
  ops = [(lambda k:(lambda p, d: p.__setitem__(k, p[k] + d) or p))(k) for k in [0, 1]]
  while True:
    for d in [1, -1]:
      width += 1
      for op in ops:
        for i in range(width):
          yield tuple(op(p, d))
あっ。でもJava側のコードみたいに「次に進める関数」を作ってこう書く手もありますね。
>>> lambda x, y, width, i, phase: [
	[0, 0, 1, 0, 1],
	[
		x + 1,
		y,
		width,
		[i + 1, 0][i + 1 == width],
		[1, 2][i + 1 == width]
	], [
		x,
		y + 1,
		width + [0, 1][i + 1 == width],
		[i + 1, 0][i + 1 == width],
		[2, 3][i + 1 == width]
	], [
		x - 1,
		y,
		width,
		[i + 1, 0][i + 1 == width],
		[3, 4][i + 1 == width]
	], [
		x,
		y - 1,
		width + [0, 1][i + 1 == width],
		[i + 1, 0][i + 1 == width],
		[4, 1][i + 1 == width]
	]][phase]
<function  at 0x012AF770>

>>> args = [0, 0, 0, 0, 0]
>>> (globals().__setitem__("args", f(*args)) or tuple(args[:2]) for i in range(10))
<generator object at 0x00DAA6E8>
>>> for p in _:
	print p

	
(0, 0)
(1, 0)
(1, 1)
(0, 1)
(-1, 1)
(-1, 0)
(-1, -1)
(0, -1)
(1, -1)
(2, -1)
もちろん、人間に読みやすく改行は入れてあるものの、本質的に一つの文で書けるので、こう書いてもOK(ぇ) 不必要なスペースを取り除けばまだまだ縮みますよー。

2006年11月05日

日記

携帯の充電ケーブルも持ってくるのを忘れた。 家では充電器で充電して、充電ケーブルはカバンに入れっぱなしにすべきかも知れない。


__ 距離Dだけ離れた半径rの2つの円の間を円弧でなめらかにつなぐことを考える。直線でつないだ場合に比べて0.5rだけ凹むような円弧の中心角は、4 arctan(r/D)。想像以上にシンプル。


__ プラグイン外部のJarにくくりだしてしまったプラグインは 本体側のメソッドの返り値を変更すると、リフレクションを使っていなくても そのメソッドを見つけられなくなる。 「RenderableVertex getNearestVertex(double, double, double)」 を 「IVertex getNearestVertex(double, double, double)」 に変えたせいで 「java.lang.NoSuchMethodError: org.nishiohirokazu.grinEdit.Mediator.getNearestVertex(DDD)Lorg/nishiohirokazu/graph/RenderableVertex;」 というエラーが出るようになった。

ということは他のプラグインも全滅だろうなぁ。


__ 辺が7本のグラフ一覧を出して遊んでいたら全部辺が交差しないように配置することができた。そういえば辺が8本以下のグラフは全部、辺が交差しないように配置することができるんだった。9本でも例外は1個だけ。


__ 日経4946の読み方を忘れて、「日経よくしろ」かと思った。


__ 電車に乗ると作業がはかどるかどうかを確認するために、大阪市営地下鉄の中央線を往復して、間違えて乗車駅で降りて駅員さんに怒られた。

Pythonのジェネレータで四角いらせんを書いた

Javaで書く必要があったのですが。
>>> def squareSpiral():
	width = 0
	(x, y) = (0, 0)
	yield (x, y)
	while True:
		width += 1
		for i in range(width):
			x += 1
			yield (x, y)
		for i in range(width):
			y += 1
			yield (x, y)
		width += 1
		for i in range(width):
			x -= 1
			yield (x, y)
		for i in range(width):
			y -= 1
			yield (x, y)

			
>>> g = squareSpiral()
>>> for i in range(10):
	print g.next()

	
(0, 0)
(1, 0)
(1, 1)
(0, 1)
(-1, 1)
(-1, 0)
(-1, -1)
(0, -1)
(1, -1)
(2, -1)
とこんな風にアルゴリズムが正しく動いていることを確認してからJavaで書く。 Javaっでこのアルゴリズムを実装しようとすると、 「ループの中でフラグを立てておいてループの外でそのフラグをチェックしてさらにbreakする」とか「上のコードでどのループの中にいるのかに相当する変数を持っておいて、それに応じてnextが呼ばれたときの挙動を変える」とかが必要なのだけど、 いきなりそういうごちゃごちゃしたのを書くとエンバグ率が高い。

だから仕事では100%Javaを使うという人にも、Pythonを学ぶメリットはあるのです。 なんて当たり前すぎる結論かな。


__ で、上のコードを眺めながらJavaで書いてみました。

private void init(){
	phase = 0;
}

private void next(){
	if(phase == 0){
		x = 0;
		y = 0;
		phase = 1;
		width = 1;
		i = 0;
	}else if(phase == 1){
		x += 1;
		i += 1;
		if(i == width){
			phase = 2;
			i = 0;
		}
	}else if(phase == 2){
		y += 1;
		i += 1;
		if(i == width){
			phase = 3;
			width += 1;
			i = 0;
		}
	}else if(phase == 3){
		x -= 1;
		i += 1;
		if(i == width){
			phase = 4;
			i = 0;
		}
	}else if(phase == 4){
		y -= 1;
		i += 1;
		if(i == width){
			phase = 1;
			i = 0;
			width += 1;
		}
	}
}

public static void main(String[] args) {
	// test
	SeparateComponentLayout s = new SeparateComponentLayout();
	s.init();
	for(int i = 0; i < 10; i++){
		s.next();
		System.out.println(s.x + ", " + s.y);
	}
}

結果がPythonと同じになることを確認。めでたしめでたし。どちらも一発OKだったので非常に楽でした。最初からJavaで書いたらこうはいかなかったかと思います。

2006年11月04日

携帯から

あー。手帳に出張に行く時のチェックリストを作ったのにチェックを忘れた。前回通帳を持って帰ったのに印鑑を忘れたので今回は忘れたないように気を付けていたらパソコンの電源を忘れた。プレゼンしに行くのに…。まあ他のマシンので代用するしか。 ベルトしめてくるの忘れた すいてるように見えるがなあ。三人席でカップルの隣。 喉の調子悪い

日記

ADHD漫画で解説サイト フロンティア★ADHD!!。 マンガでADHD。

__ 空のハッシュを値に持つハッシュを出力したときのJYAMLのこの挙動は正しいのか?

params: !java.util.Hashtable
  target: !java.util.Hashtable
  id: Anchor
自分が出力したくせに自分でロードに失敗するの。
params: !java.util.Hashtable
  target: !java.util.Hashtable {}
  id: Anchor
なら問題ないのだが。

空のハッシュがある部分に手作業で「{}」とつける、という条件付きで、YAMLでの保存とロードが完成。具体的には、一つ以上の頂点がアンカーされていない場合には悲しいことになる。


__ Eclipseのコードテンプレートに dpという名前で「System.out.println("DEBUG@${enclosing_type}#${enclosing_method} ${cursor}${var}:" + ${var});」という内容を登録した。debug printの頭文字。 これで「dp Ctrl+Space」と打つとそれがどのクラスのどのメソッドかの情報が勝手に入って例えば「System.out.println("DEBUG@Mediator#loadClass var:" + var);」というようになる。さらにvarのところにフォーカスがあっているので、そこで表示させたい変数の名前を入れるとvarのところが両方それに書き換わって楽ちん。 デバッグが終わった後も、プロジェクトの中をDEBUGで検索して該当のデバッグ出力を消せばいい。 うっかりデバッグ出力を消し忘れて見苦しい出力のでるリリースをしたりしない。


__ 隣のカップルは、幸いほとんど寝ているので邪魔にならない。


__ 僕もだんだんJavaに染まってきたのかも。 当初使い始めた頃は「Interface?へんなのー」とか思っていたのだけど、レンダリングの関係ない純粋にグラフ理論的なところでRenderableVertex、RenderableEdgeなんて型が出てくるのが気にくわなかったのでIVertexとIEdgeを導入したらすごくきれいになった。ちなみにIVertexは空っぽです。グラフ理論的には頂点の集合は任意の集合でよいので、それをプログラムで表現すると空っぽのインターフェイスになります。IEdgeは2つの頂点のgetterを持ちます。

あっ。IVertexのscreenPosにアクセスできないってエラーがっ(汗) IHasScreenPosを作るしかないか。Vector<IVertex>はVector<IHasScreenPos>にはキャストできないぞ。ループの中でIVertexからキャストするしかないのか?うむむ?

なんかJavaっぽくなったのか単にダメになったのかよくわからない。

あー。どうするべきかわからなかったので曖昧にしていたところを突かれた。RenderableEdgeがバネの自然長やバネの強さを持っているのはどうなのか、と。これはバネの力を発生させる物理演算にめちゃくちゃ密結合じゃないかと。正直に言うとlengthの値が-1の時にはデフォルトの辺の長さを使います(ぇー)。

これは以前Vertexが持っていたanchoredPosを「これはアンカーをかける物理演算が持つべき」って言ってPL_Anchoredに移動したのと同じか…。物理演算に移動すべきなんだな。

今、米原。バッテリー残量10%。

移動できた。でもまだ「できた」と言ってはいけない。以前できた「辺の自然長やバネ係数を変える」という操作ができなくなっているのだから。以前は辺eを取得してe.k = 0.0でバネの強さを消すことができたけども、今後はPL_SpringEdgeのインスタンスlawを取得してlaw.setSpringStrength(e, 0.0)とやらなければならない。そのAPIを作らなければならない。

二つめのバッテリーにチェンジ。あと3時間活動できる。それまでには大阪に着く。

そうか。vertexがselectedを持っている問題も、SelectionがXML-RPCからアクセスできない問題も、おなじことか? いや違う。PL_Anchorがアンカー位置の情報をほしがったり、PL_SpringEdgeがバネの自然長をほしがったりするのは、両方とも主体が物理演算だ。でも選択された頂点をハイライト表示するのは主体がレンダラーだ。レンダリングは今、おのおのの頂点がrenderメソッドを持っているわけなので、Vertexが自分をハイライト表示でレンダリングするためには、ハイライトされるべきだという情報をレンダラーからもらわないと行けない。物理演算が主体の場合は、物理演算が対象となる頂点の位置を変更するわけだが、レンダラーがrenderメソッドを差し替えるわけにはいくまい。もし頂点に「ハイライトされるべきフラグ」をつけてそれを操作するのであれば、今と何も変わってない。変数名がselectedからhighlightedに変わるだけ。

ってもう新大阪だ。


__ どうして移動中の電車の中では作業がはかどるのか。僕の考えでは、意味のないノイズが大きいので逆に外界をシャットアウトできる点と次に中学以来の通学により「電車の中では考え事をする」という条件付けがされている点が原因。母の意見では、電車に乗って移動することが位置記憶も司る海馬に刺激を与えるので、周辺の大脳辺縁系全体が活性化されるのではないかとのこと。眉唾。でもNucleus accumbens - Wikipedia, the free encyclopediaには「Major inputs to the nucleus accumbens include the prefrontal cortex, amygdala, hippocampus,…」と書かれているので、海馬に対する刺激が側坐核を興奮させるのは事実っぽいなぁ。移動しないで電車に乗ることができれば(具体的には庭付きの家に住んで庭に電車を置くとか)なにか知見が得られるかも知れない。そんな実験に研究費は出ない。


__ 上記のJYamlの問題点は、「空のリストのdumpに問題がある」という形で6ヶ月前にバグレポートされているなぁ。 自分でJYamlに手を入れるしかないかなぁ。

あー。出力はJYamlを使わずに自前でやるというのも手か。 それならば、例えば省略可能な「org.nishiohirokazu.graph.」は省略するとかできるしなぁ。それがいいのかも。

でも今日はたくさんリファクタリングしたので、明日はデモンストレーションを一通りやってきちんと動くことを確認しないとね。

2006年11月03日

再開二日目の日記

起きて「治った!」と実感できないと言うことは治ってないんだろう。喉に痰が絡むし、扁桃腺もまだ少し腫れて熱を持っている。でもまぁ、だいぶマシ。

__ この時期って新幹線混んでるんだなぁ。こだまのグリーン車なんか前使ったときは車両に2人だけで、新大阪から東京まで通算でも4人だったのに、明日大阪に行くこだまの予約を取ろうと思ったらグリーン車は満席ですとのこと。 4時間グリーン車で作業をするとはかどるんだけどなぁ。

ちなみに東京・品川発|ぷらっとこだまプラン|JR東海ツアーズです。普通車はあいているとのことだったのでそちらに。騒がしかったりするとイヤだからイヤホンを持って行かないと。


__ どうでもいいけど「空いている」は「すいている」のか「あいている」のかわからない。


__ 月曜日に阪大でGRINEditの話をするのでそれに向けて準備しないと。


__ livedoor ニュース - ◎側溝ふた盗んだ4人逮捕=1キロ150円で転売-神奈川県警。100万円の利益が上がったらしい。側溝のふたは30キロ~46キロ程度のものらしいので、おおざっぱに言って5000円札が置いてあるようなもの。

僕は盗ろうとは思わないけど、盗ろうと思う人が出ても不思議ではない。


__ Jythonがなかなかバージョンアップしないのは、最新の情報(英語)をネットから取る人間にとってはデメリットだけども、日本語の本を欲しがる人間にとってはさほどのデメリットではないのかも知れない。むしろ「本に載っているのは古いバージョンだけど、新しいバージョンのことがわからないから仕方なく使っている」という負い目を感じなくて済むという意味ではメリットだ。


__ プログラマの三大美徳についていい訳がないか検索していたら、 いやなブログ - 読解いやな法則: 横着をするための労力を惜しんではいけないが見つかり、「おお、リンク張ってある、この先にあるのは英語かな和訳かな?」と思ってクリックしたら自分の日記だったorz。(プログラマの三大美徳を和訳してみた @ NISHIO HIROKAZU # Archived COREBlog)

割と自信のない訳出なのだけどなぁ。とりあえず「三大美徳の1番目であり」は「第一の美徳であり」のほうがいい気もする。

原文に忠実でなくてよければ「全体として必要な労力を最小にするために労力を惜しまない性格」でいいんだけどね。


__ うーん。2玉250円だったので喜んで買ってきたハクサイは、冷蔵庫に入らないので外に置いておいた方の玉が袋の中で茶色い汁を出してます…。やっぱりそうなってしまうか…。

うまく腐っていないところを切り取れば食べられるかも知れないけど 「捨てることも重要」かもしれない。「使えるかも知れない」と思って 料理を作った後の汁を取っておいたり、「食べられるかも知れない」と思ってキャベツの芯を煮てみたりすることがいろいろな問題を発生させたから。 とりあえず明日から不在なので、帰ってきたときにどうなっているかを見て判断しよう。


__ 月曜日に通帳の印鑑を変更しよう。


__ はっ。tDiaryのほう、ほったらかしにしてたらびっしりとコメントスパムが付いている!やだなぁ。どうしよう。コメントを受け付けないようにするとしても、今付いているコメントを除去しないと気持ちが悪い。


__ 作業ログを書くことはすごく重要。 でも、どういうログを書けばいいのかは自明ではない。

考えたことをすべて書けばそれでいいのか?

この日記は「考えたことをすべて書いてあるもの」なのか?否、公開できない大半のことは考えても書いていない。 本当は、非公開の考えたことをすべて書いてあるブログを作って、何らかの方法で自分だけは検索できるようにして、公開してもいいものだけ後から公開する方がいいのかも知れない。


__ 考えたことを書き記すフォーマットとしては直線状の文章がよく使われるが、これは必ずしも唯一のフォーマットではない。音声と聴覚を使ってやりとりをするために発生した言語なので視覚的に捉えるのには向かない。箇条書きやマインドマップはそれより多少視覚に訴える。特にマインドマップは視覚に訴えるかを重視したフォーマットだ。

個人的にはマインドマップでも自分の脳の中を表現するには自由度が足りない。脳の中の概念は相互につながりあったネットワーク状の構造になっているように思う。これを自然に表現すると、グラフ理論の意味のグラフになる。

グラフでならば、もつれた、整理されていない考えをそのまま整理されていないまま記述できる。そこから辺に「親子関係」「たまたま連想しただけで親子関係でない」というラベルをつけていくと箇条書きができあがる。また、このグラフの主要な頂点を1本の糸でつないで、間を適当に埋めると文章ができあがる。

グラフが一番脳というデバイスの特性に沿ったフォーマットであり、文章が一番喉というデバイスの特性に沿ったフォーマットなのではないだろうか。

このそれぞれのフォーマットをうつり歩くことで考えが整理される。 例えばいきなり文章として書けなくても、いちど箇条書きにして、それを改めて眺めると文章の筋道が思いついたりする。グラフというフォーマットは、一番整理されていない状態の思考を表現することに適したフォーマットである。このフォーマットで書き出すことで、より思考が整理される可能性は高い。

毎日、普通の文章で日記をつけているケースを考えよう。 おのおのの日記はただの文章だが、その中のあるキーワードはいくつもの日記に出現する。仮にGRINEditとする。僕のイメージでは、この日記の文章は「中身に文章フォーマットで色々書かれている頂点」であり、カメラをぐっと引くと、「GRINEdit」と書かれた頂点へつながっている。GRINEditと書かれた頂点からはまた他のいろいろな頂点へつながっている。

時系列ソートは必ずしも必要ないかと思っていたけども、やっぱり必要かもね。 実際には表現するのが大変だから表現していないだけで、それぞれの頂点は「生成時刻」という時間軸上の一点に対応付いている。仮に見ている画面がモニター上の2次元のだとすれば、モニターの奥の方に向かって過去が続いている。1時間前のメモが1センチ奥にあったり、1年前のメモがずっと奥にあったり。古いものを薄く表示するとかは、この空間にフォグをかけるというだけのこと。時系列表示というのはこの空間をモニターの横側から見ると言うこと。

時系列にソートすることが重要なのではなく、時間軸方向にトラベルできることが重要なのだ。 フォグのかかった画面で、自分が「現在」にいれば、新しい頂点ほどはっきりと見える。古い頂点はぼやけて見える。見やすいものから見れば新着順。自分が過去の一点に「外の人」としてタイムトラベルしたら、その時点前後の、近いものほどはっきり見える。「中の人」としてタイムトラベルしたら、その時点より未来のものは見えず、その時点で自分がモニタ越しに見ていたであろう映像がそのまま見える。

Subversionを使おうかと思ったり。 シリアライズしたときに頂点IDが変わるのだったか変わらないのだったか。 確かどちらも選べてどっちでも大した問題ではないのでどちらかにしたんだった。時系列で一貫性を保つと言うことを考えるとIDは絶対に欲しくない。

フォグのたとえでは、重要なものが普通に見えて、そうでないものが見にくく見えるだけだが、もちろんこれは重要なものがハイライトされるようにしても、NEXTボタンで重要な順に開いていくようにしても構わない。そこは本質的ではない。ユーザに使いやすいようにすればいい。

howmの説明(index.rd)を読む。これはなかなかいい。

howmはけっこう、僕が目指していたものに近いのかも知れない。ここから僕が目指しているものへの道は3文字の質問をすると見えてくる。「図は?」

GRINEditにhowmモードをつけるのが一番手っ取り早そう。重たい可視化付きで嫌がられそうだけど、僕が使いたいから使う。


__ 今気がついたんだけどMORI LOG ACADEMYの絵ってハチクロの人のだね。


__ オフラインでもsvkを使ってリポジトリにコミットしながら作業ができるが、 Tracが使えない。TracもローカルTracとかあればいいのに。データをSubversionのリポジトリとして持っているBTSがあれば済むのに。


__ 「どうせ捨てるからサポートしない」と言っていた GRINEditの古いフォーマットのローダー、簡単に現状のAPIにあわせて変更できました。簡単でした。前よりもAPIが簡単になったから?

Enumerate graphesのデータをそのフォーマットに変更するのもできました。簡単。 もっと早くやればよかったです。549個の頂点がある「すべての7本の辺からなるグラフ」(リンク先の図と同じ物)はさすがにFPSが20くらいに落ちますね。開いた瞬間は密集しているから7FPSくらい。

1746頂点の「すべての8本の辺からなるグラフの集合」はロードに7秒かかって、その後3FPS。もちろん従来の自動整形の研究の観点から言うと 「収束までに尋常でない時間がかかる。グラフの自動成型の方法としては使えない」となることでしょう。ここはよくつっこまれるところです。けど問題は「1746頂点のグラフを自動整形したものは人間にとってわかりやすいものかどうか」ということです。僕は「そうではない、ユーザの理解を助けるためには要約して頂点数を削減するべきだ」と考えているというわけです。

もちろんこれを高速化する方法はいくつもあるわけですけど、あんまりそれらのサポートには積極的ではないのです。どちらかというとGRINEdit + PlaggerとかGRINEdit + howmとかの方に興味があります。

ロード時には一時停止されているわけだから、計算再開前に「静的整形エンジン」を走らせるのも一つの手ですね…。それなら今の枠組みを壊さないか…。ドラッグ&ドロップハンドラをプラグインで追加できるのと同じような感じで邪魔なら消せるし好きなのを追加できる形で。


_

_ 寒い&熱上がってきた。やばい。 明日は電車の時間が決まってしまったので寝過ごせないし。 家の鍵とか印鑑とか必要なものを探さないと行けないし。 寝よう。


__ 「寝る前に家の鍵を見つけておかないと」と思って探していたのですけど、 見つかりません。代わりにブルーベリーのハチミツ漬けの瓶が発酵して汁を出して床を汚しているのや、ヨーグルトの空き容器から垂れたヨーグルトがMP3プレーヤーを汚しているのを発見。掃除。そして鍵は見つかりません。どこへ行ったのでしょう。

記憶が確かなら「この鍵はこっちでは使わないから持ち歩くのはよくない。実家に帰るときに使うこのカバンに入れよう」と言って普段使わないナップサックに入れたのですけど、ナップサックには入っていません。判子や印鑑を入れている箱にも入っていません。いったいどこへ行ったのでしょう。


__ ロード後に実行される静的な整形エンジン、というアイデアは実は結構いい気がしてきました。GRINEditの動的な整形に批判的な人を納得させる材料として。自動整形のチェックを外しておけば、単純にファイルをロードすると静的な整形エンジンが走って、静的に整形されたグラフが表示される、マウスで頂点を移動できる、もし再度走らせたければメニューから選べばいい。まったく何の問題もなく「GRINEditの長所である動的な整形を殺して」静的な整形機能だけで使うことが出来ます。

後はちょっと発想を逆転すれば、まず全頂点をアンカーした上で、選択した頂点だけアンカーを外して、自動整形をONにすれば「選択した部分だけ物理演算で整形」ができますね。もったいないことにアンカーされている全頂点のぶんだけ計算量を食いますけど。

そんなことしなくても一度物理演算を全部はがしておいて、選択された頂点に対して物理演算を追加すればいいのか…。ふむふむ。

あ、そうすると選択されていない頂点との間に反発力が発生しない。やっぱり最初の方法が適切か。

頂点や辺が自分自身を追加するメニューを追加できるといいな。Javadocコメントじゃなくてプログラムが読める形でドキュメント文字列を持たなければ行けない。それも英語とか日本語とか切り替えられないと行けない。それをJavaのコードで書けるようにしないと行けないかと思ったけど、よく考えたらプラグインとして追加されたJarの中のどのクラスがメニューに出して欲しいものかはわからないので、全部リフレクションでgetDocumentを叩くというのもなんかアレである。Pythonで書いてもらうのが一番よさそう。regsterVertexみたいな感じのを呼ぶだけ?

2006年11月02日

日記

生きてますよ!

前に起きたときは「6時か…朝かな?夜かな?夜か…」だったのですが今日は「7時か…朝かな…夜かな…って明るいな…」でした。おとといは元気で、食料を買いに行って買い込んできたんですけどねぇ。油断していたら昨日は熱と頭痛と吐き気の三重苦。やれやれ。油断禁物。


__ おとといは元気だったので買い物に出かけて、通常1/4玉で100円のハクサイが、2玉で250円という謎の値段で売っているのを発見して喜んで購入し、帰りの道でドラッグストアが「今日だけ冷凍食品50%オフ」をやっているのを見つけて冷凍ピラフ系のものを買い、冷蔵庫も冷凍庫もあふれかえりそうになりました。


__

今豪雨が降って西船橋が2メートル浸水しても、僕は1週間くらい生きられます。ただし電力必須。


__ taosさんの日記から。 CGTalk - Song Hye Kyo, Korean Actress (WIP)。 実在の人物の写真が12枚あるように見えますが、1枚はCGです。いやはや、最初12人の写真と思っていた僕にはさっぱりわかりません。 答えはリンク先の写真の下に続いている作業過程を見ればわかるんですけど、いちおうヒントは↓

↑でも、作業過程を見てからじゃないとわからなかったです。

__ 健康になると血行がよくなる。血行がよくなるとかゆくなる。お風呂に入りたくなるのは健康になった証拠。


__ あっ。もう28時だっ。ちょっと体調がよくなると調子に乗って夜更かしするからいつまでも直らないんだ。 でも、今日は扁桃腺の腫れも収まったしいい感じ。牡蛎鍋を作って残りの汁で卵おじやを作って食べたので栄養が充実したのだろうか。柿も食べたし。

おじやは普段の1食分の0.5合だと作りにくいので1合で作ってしまい、0.7合くらい食べてのこりを残した。これは明日の朝食べよう。

柿は、ニンジンの皮を剥くのに使っているピーラーを使うと簡単に皮がむけることを発見。 小さい果物ナイフがあるといいのだけど、大きい包丁しかないので…。包丁でむくのが大変だからとピーラーを使ったら想像以上によかった。ナイフタイプの(よくあるT字型のじゃない)ピーラーはナイフ代わりに使えるなぁ。


__ 今日は祝日なのだろうか?どの祝日が月曜に移動して、どの祝日が移動しないのかよくわからない。いっそのこと毎週月曜日はお休みにするといいと思う。