« 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 秋元@サイボウズラボ・プログラマー・ブログ: 音痴チェッカー。 最初「『ブー』と音が鳴ってドかミか選べとい