« 2006年05月 | メイン | 2006年07月 »

2006年06月29日

log

MenuActionを継承した具体的なクラスは全部MA_で始まり、 MouseOperationを継承した具体的なクラスは全部MO_で始まるので、 PhysicalLawを継承した具体的なクラスは全部PL_で始めることにしました。

剛体の実装に着手。剛体のような「めったに構成する頂点が変わらないようなもの」に関してはVectorではなく配列にしてしまった方がいいのかも知れないと思ってそういう実装にしてみました。しかし、この設計が必ずしも正しいとは言えないので時間が経ってから考え直す必要があるでしょう。

実装は出来たので次はそれをテストするための仕組み。メニューに「選択範囲をグループ化」をつける。

慣性がないのがなぜ自然か

物理学としては「力が働かないものは動き続ける」というのが自然であり、加速度が与えられないものは速度を維持するというのが自然です。しかしユーザーインターフェースとしては自然ではありません。それはなぜでしょうか。

それは人間の素朴物理学(naïve physics)と正しい物理学との間には乖離があるからです。いい参考資料があったのでリンクしておきます(認知学習論(ppt)

結局のところ人間が素朴に持っている物理学が正しい物理学に一致していない以上、物理学的に正しいことよりも素朴物理学的に正しいことを重視しないと行けません。多くの人は静止している物を見たときに「無重力空間で空中に浮かんでいる物体」をイメージしません。「机の上に乗っているコイン」の様なイメージを持ちます。力をかけている間は動きますが、力がなくなると止まるのが自然なのです。

日記

新幹線でLANが使えると幸せですね。2009年の予定ですけど。

人力検索はてな - ライセンスの問題です。CPL(Common Public License)で配布されているソフトウェアのソースコードを参考にして自分のLGPLで配布しているソフトウェアに機能を追加したいので..によれば、CPLのコードをプラグインという形でLGPLのプログラムに組み込むことは問題なさそうです。つまり、graphvizのコードをプラグインという形でGRINEditから使えるようにすることには法的な問題はないということです。

サーベイ能力弱いなぁ、僕。GraphvizのJavaによるラッパーがありますね、Grappaっていうのが。no longer activeですけど。これもCPLならこっちのコードを使う方がいいかもしれませんね。no longer activeだからこっちでいじっている最中に向こうがガシガシ書き換わることもないでしょうし、向こうにとってももうメンテナンスする気がないのですからこっちが引き継いでも損にはならないですし。

昨日のカレーみたいなポトフは、冷蔵庫から出してみるとゼリーみたないなものに変わっていました。骨のついている鶏肉をぐつぐつやったからかな?まだ2食分くらいあるので今日はこれにカレールーを入れることにします。

コラーゲンは骨から出たのか軟骨から出たのかどっちだろう。

JUNG - Java Universal Network/Graph FrameworkのFAQを参考にしよう。英文の。


__ 暑い。 さすがに冷房を効かせれば暑くはないんだけど、出勤過程が暑いので涼しくなっても汗臭い。


__ グラフの可視化を簡単に説明するサイトを探そうと「グラフ 可視化」で検索したら秋元@サイボウズ研究所プログラマーBlog: HTML構造のグラフによる可視化が一番上に来ました。


__ ダメだダメだダメだ、GRINEditリリース後しばらく遠ざかっていたせいで何をしたらいいのかが頭から消えていた。 消えないようにTODOとか作業ログとか書いていたのに、書き方が悪くてダメだ。

頭の中にあることを単に全部吐き出してしまうだけではなく(もちろんそれも書き忘れたことを後で探す必要が出来たときには重要だが)簡潔・最小限の「未来の自分への手紙」を書いておかないといけない。 やろうと思ったことを忘れないためには「Aをやろう」「Bをやろう」「Cをやろう」と全部書き留める必要があるが、次に再開した時に自分がタスクに押しつぶされたり道に迷ったりしないためには「次はアレをやろう」をわかりやすいところに書いておく必要がある。

角運動量の計算で外積が出てきたので結局「3次元だけども2次元に拘束されている世界」になってしまった。美しくない。いっそ3次元にしてしまった方がいいのだろうか。ほとんどの人にとって3次元は必要ないと思えるし、3次元にすると必然的に今の「平行移動」の他に「回転」が必要になる。別に出来なくはない、というか実は過去に3次元のバネモデルは 作りかけアプレットで使っているので目新しい問題点はないのですけども。うーん。ニーズがないと思うしなぁ…。

もう9時?!


__ だいぶ家事がうまくなったかも知れません(あくまで過去の自分と比べて)。 帰ってきて、薬罐に麦茶のパックと水を入れてお茶を沸かしている間に、 冷蔵庫から昨日のポトフの鍋を取り出し、チンして冷凍して置いたニンジンを入れて、タマネギの残りを入れ、沸いた薬罐と取替え、炊飯器にお米と水を入れてスイッチを入れて、今ぐつぐつと鍋が煮えているところです。 炊飯器は一番最初につければ良かったってのと、鍋に水を入れすぎてちょっとこぼれ気味なのが反省点ですね。あと時々新聞と一緒に入っている茶色の袋が、実はかなりマチが広くて読み終わった新聞を入れられると言うことに気がつきました。(っていうか古新聞を入れるための袋ですね、これ)。縛らなくていいので楽です。

お茶はいつも2リットルの水を入れて沸かしていたのですが、水出し麦茶のパックで出すとかなり濃く出るので2リットル沸かしても4リットルに薄めて飲んで大丈夫です。そこで「1リットル沸かして2リットルに薄めればいいじゃん」と気がついてお茶が沸くまでの時間を節約できました。

家事もハックですね。しかもマルチスレッド。


__ Grappaはおそらくレイアウトの機能を全く持っていないですね。dotファイル自体が頂点の位置などの指定された物に指し変わっています。とりあえずJavaで書かれたdotパーサは再利用できそうです。Cで書かれたgraphvizのコードを読むのと、graphvizのコードにコメントとして書かれていた論文を読むのとどっちが手っ取り早いかな。

graphvizを読めば読むほど、たいしたことがないように見えてきます。とりあえずレイアウト方法は6通りあって、そのうち2つはGRINEditと同じバネモデル。残りは階層的レイアウトと円形レイアウトと放射状レイアウトですね。円形レイアウトはJ. M. Six and I. G. Tollis, A Framework for Circular Drawings of Networks, Proc. of GD 99, LNCS 1731, Springer-Verlag, pp. 107–116, 1999に載ってそうです。ググって見つけたSymeonidis and Ioannis G. TollisのVisualization of Biological Information with Circular Drawings Alkiviadisが数ページを割いて解説しているのでまずはこれを読んで、原典に当たる必要があればそうしましょう。

2006年06月28日

日記

今朝夢の中で阪神大震災の予震が3倍くらいの長さになったような地震を感じたのだけど、実際に地震があったらしい9時45分には起きていたと思うんだけどな。シャワーを浴びて地震情報を検索している今が9時55分だもの。でも起きているときに地震を感じていないのも考えると…やっぱり寝てたんだろうか?

また洗濯物を干すの忘れて放置してる…。 あと一昨日買った鶏肉のことも忘れてた…。傷むと困るから冷凍庫にいれとこうかな。 今日は早めに帰って一昨日買った野菜を調理しないと。


__ 論文提出完了。


__ Brainf*ckが一部で流行っているみたいなので An introduction to programming in BF へのリンクを張っておきます。


__ 今年度の若手の会(第39回情報科学苔手の会) の申し込み。GRINEdit発表するのも悪くないかもなぁ。


__ 下期の未踏って終わるのが来年の9月末なんですねぇ。思っていたよりも長いです。


__ Boost勉強中、と言ってもC++のBoostではなくAdaBoostですが。


__ 書かないと気になって集中すべきことに集中できないので書いておきます。 PythonBrainf*ckコンパイラの話ですが、一応周囲のコマンドの情報から適切なGoやKillを挟むようにはなったので次はコード内で領域の確保が出来るようにしたいわけです。その為にはどこが破壊していい領域でどこが破壊しては行けない領域かを知る必要性があるわけです。それと、現在は [ ] を使ったジャンプが生で直接操作されるようになっていますが、これはp回繰り返すTimes命令 [- (command) (go p)] やIf命令(Kazuho@Cybozu Labs: brainf*ck で計算機を参照)を作っておいてそれを使うようにし、生の [ ] はなるべく使わないようにすることで1カ所のミスが全体に波及して困難なバグを生み出す可能性を減らすことが出来ます。 そうすれば、Times命令が使う領域に「破壊禁止」のマークをつけた上でその中身のコマンドをコンパイルすることで中身のコマンドが新しい領域を確保しようとした場合にTimesの作業領域を破壊することが防げます。

デジャヴですね。これぞ構造化プログラミングの誕生です。

必要な変数は最初に全部宣言してしまうタイプの方が、whileやifが現れるたびにその場であいている領域から作業領域を確保する今作っているようなタイプよりも楽でしたね…。

それはさておき、Brainf*ckで特定の数を作るための最小のコマンドは何か、という問題は作業領域として使っていいセルがどこにあるかによって異なりますね。[0]以外は全部使っていいとするのが問題としては一番簡単ですが、コンパイラを作る側としてはそれでは実用性がないわけです。Brainf*ckには元から実用性がないじゃないかというつっこみは禁止。

Cを機械語にするのは機械語コンパイラじゃなくてCコンパイラで、JavaをバイトコードにするのもJavaコンパイラだから、PythonをBrainf*ckにするのはPythonコンパイラ(違う) 任意のPython言語がBrainf*ckになるわけではないので、あくまで「Pythonで実装された小さな言語」のコンパイラなのですね。じゃぁPyBrainf*ckコンパイラって呼ぶことにします。


__ Pythonは2.4あたりから複数同時に起動しようとすると怒るようになったので、 何かプログラムを書いていて時間のかかる処理を実行した後、待ってる間に別のプログラムを書こうとすると対話的に短いコードのテストとかが出来なくて不便です。何とかならないんですかね。 しばらく考えてCygwinのPythonを起動しましたがコピペ出来ないから不便…。


__ おなかすいたなぁ。


__ 腰が痛いなぁ。 いい椅子のはずなのに何故だろう。


__ ふう。そろそろ帰ろうと思ったのでBrainf*ck(ぇ)

もっと完成してからまとめて公開するので今日はクラス定義は全部省きます。

e = Environ()
e.nameSpace.update({"A":0, "B":1, "C":2})
print "".join([x.make() for x in [
	Copy("A", "tmp1", "tmp2"),
	Copy("B", "C", "tmp2"),
	AddTo("tmp1", "C")]])

name tmp1 not found alloc. at 3 name tmp2 not found alloc. at 4 [>>>+>+<<<<-]>>>>[<<<<+>>>>-]<<<[>+>>+<<<-]>>>[<<<+>>>-]<[<+>-]
bf = BFInterpreter()
bf.simplify("""
+++>++++< # [0] = 3, [1] = 4
[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<<<[>+>>+<<<-]>>>[<<<+>>>-]<[<+>-]
(showMem)
""")
bf.runCode()

0 3 1 4 2 7 3 0 4 0

Brainf*ckインタプリタはコードの中に括弧で囲ってデバッグ用のコマンド(メモリダンプやassert, 任意文字列のprintなど)を入れられるようにしました。PyBrainf*ckコンパイラの方は、名前空間を処理系が1つだけ持つ(原始的な)形に変えました。実装がすごく楽でした。

あ、もう8時だ。晩ご飯食べて帰っちゃダメなんだった。野菜と鶏肉が僕を待っている…。


__ ポトフ作りは暑くて大変です。

スープは悪くない味だと思うのだけど(っていうかコンソメだし)タマネギを食べてみると味がしみてないのはなぜでしょうねぇ。もっと煮ないといけないのかなぁ。

そういうわけでさっきからずっとぐつぐつやっています。


__ 出来ました。 これポトフなんでしょうか。 なんか、カレーみたいなにおいがします。カレー粉とかは使っていないのでもちろんそういうにおいではないのですけど「タマネギやニンジンを煮詰めました」というにおいがします。それから何か予想と違ってかなり茶色いです。いわゆるカレーほどではないですけど、こういう色のスープカレーはありそうです。最後に、割と辛いです。コンソメだけではぼんやりした味だったのでこしょうを瓶のふたに半分くらい入れたからだと思います。食べると汗が出ます。


__ Kazuho@Cybozu Labs: brainf*ck でマジメに素数探索

ひゃー。もう解かれちゃいましたか。

こちらの現状は「[1]が[0]で割り切れるかどうかを判定するBrainf*ckコード」を生成するプログラムが出来たところでした。素数への道のりはまだ遠い…。

e = Environ()
e.nameSpace.update({"A":0, "B":1, "Result":2})
print Seq([
    Create("A", 3),
    Create("B", 6),
    Create("toLoop", 1), # True
    While("toLoop", [
        Copy("A", "tmp1", "tmp2"), # free tmp2
        Times("tmp1", [
            If0("B", Dec("toLoop"), "tmp2", "tmp3"),
            Dec("B")]),
        If0("B", Seq([
            Dec("toLoop"),
            Inc("Result")]), "tmp2", "tmp3"),
        ]),
    ]).make()

name toLoop not found alloc. at 3 name tmp1 not found alloc. at 4 name tmp2 not found alloc. at 5 name tmp3 not found alloc. at 6 (start_Seq) +++>++++++>>+[ (start_Copy) <<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-] (end_Copy) <[ (start_If0) (start_Copy) <<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-] (end_Copy) +<[[-]>-<]>[[-]<<<->>>] (end_If0) <<<<<->>>-] (start_If0) (start_Copy) <<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-] (end_Copy) +<[[-]>-<]>[[-] (start_Seq) <<<-<+ (end_Seq) >>>>] (end_If0) <<<] (end_Seq)

If0("B", Dec("toLoop"), "tmp2", "tmp3"), とかを見ると、どこを作業領域に使うかを人間が指定するのはやっぱり嫌な感じですね。 この「割り切れるかどうか判定」を一つのコマンドにまとめると IsDividable("A", "B", "Result", "tmpToLoop", "tmp1", "tmp2", "tmp3") になります。おぞましい。 作業領域の指定は省略できるようにして、省略した場合は適当に確保することにしましょうかねぇ。 必要になったときにメモリに「使用していますマーク」をつけて、いらなくなったときに「使用していますマーク」を消せばいいんですよね…。

AB間の移動が5回、BC間の移動が4回、CA間の移動が3回ある場合に、移動距離が最短になるようにABCを並べる方法は、っていうとまず一番大きいABを隣接させ、次にCをA側につけるのとB側につけるののどちらがいいかを調べてABCという順に決定されるわけですけど、もっと要素が多くなった場合もそれでいいのかなぁ。いや、違うなぁ。仮にA1からA100までがそれぞれ隣の数と太さ100の辺で繋がっているとして、A100とCが太さ99の辺で繋がっているとするとCはA100の側につけたくなるけど、CがA1,A2,A3のそれぞれと太さ50の辺で繋がっているならCはA1の側に行くべきだもの。難しい問題かも知れない。

PythonによるBrainf*ckインタプリタ 1.01

PythonによるBrainf*ckインタプリタ @ NISHIO HIROKAZU # Archived COREBlogの改良版です。 便利な機能としては「入出力を数字にするモード(7を入力したいときに文字コード7のものを入れるとか、7の文字コードから0の文字コードを引くコードにしておく等の面倒なことが不要)」「ステップ実行」「メモリの内容表示」「#以降行末まではコメントになる」「コメント以外でもコードに使われる種類以外の文字は無視される」などです。

## 掛け算
,>,< # 2つ値を読み込む
[-  # [0]の回数だけブロック内を繰り返し
    >
    [->+>+<<]  # [1]の内容を[2], [3]に加算、[1]は0になる
    >>[-<<+>>] # [3]の内容を[1]に加算(移動)、[3]は0になる
    <<<
]
# -*- coding: cp932 -*-
#
# Brainf*ck Interpreter
#
import sys
IO_ORD = True

class BFInterpreter:
    pointer = 0
    caret = 0
    code = ""
    def __init__(self):
        self.command = {
            ">": self.incPtr,
            "<": self.decPtr,
            "+": self.incValue,
            "-": self.decValue,
            ".": self.putValue,
            ",": self.getValue,
            "[": self.jumpIfZero,
            "]": self.backJump
        }
        self.memSpace = {}

    def incPtr(self):
        self.pointer += 1
        self.caret += 1

    def decPtr(self):
        self.pointer -= 1
        self.caret += 1

    def incValue(self):
        ptr = self.pointer
        v = self.memSpace.get(ptr, 0)
        self.memSpace[ptr] = (v + 1) % 256
        self.caret += 1

    def decValue(self):
        ptr = self.pointer
        v = self.memSpace.get(ptr, 0)
        self.memSpace[ptr] = (v + 255) % 256
        self.caret += 1

    def putValue(self):
        value = self.memSpace.get(self.pointer, 0)
        if IO_ORD:
            print value,
        else:
            sys.stdout.write(chr(value))
        self.caret += 1

    def getValue(self):
        data = raw_input("bf>")
        if IO_ORD:
            self.memSpace[self.pointer] = int(data) % 256
        else:
            self.memSpace[self.pointer] = ord(data[0]) % 256
        self.caret += 1

    def jumpIfZero(self):
        if self.memSpace.get(self.pointer, 0) == 0:
            c = self.caret + 1
            depth = 1
            while c < len(self.code):
                cod = self.code[c]
                if cod == "]":
                    depth -= 1
                elif cod == "[":
                    depth += 1
                if depth == 0:
                    break
                c += 1
            else:
                raise RuntimeError
            self.caret = c + 1
        else:
            self.caret += 1

    def backJump(self):
        if self.memSpace.get(self.pointer, 0) != 0:
            c = self.caret - 1
            depth = 1
            while c != 0:
                cod = self.code[c]
                if cod == "]":
                    depth += 1
                elif cod == "[":
                    depth -= 1
                if depth == 0:
                    break
                c -= 1
            self.caret = c + 1
        else:
            self.caret += 1

    def stepCode(self):
        c = self.code[self.caret]
        self.command[c]()

    def runCode(self):
        while self.caret < len(self.code):
            self.stepCode()

    # util
    def showMem(self):
        ks = self.memSpace.keys()
        ks.sort()
        for k in ks:
            print k, self.memSpace[k]
            
    def simplify(self, source):
        code = ""
        for line in source.split("\n"):
            for c in line:
                if c == "#":
                    break
                elif c in "><+-,.[]":
                    code += c

        self.code = code

    def removeOpposite(self, source):
        code = ""
        code = self.simplify(source)
        while True:
            prev = code
            for p in ">< <> +- -+".split():
                code = code.replace(p, "")
            if prev == code:
                break

        self.code = code



bf = BFInterpreter()

bf.simplify("""
++++++++++
[                   # The initial loop to set up useful values in the array
   >+++++++>++++++++++>+++>+<<<<-
]
>++.                #print 'H'
>+.                 #print 'e'
+++++++.            #      'l'
.                   #      'l'
+++.                #      'o'
>++.                #      space
<<+++++++++++++++.  #      'W'
>.                  #      'o'
+++.                #      'r'
------.             #      'l'
--------.           #      'd'
>+.                 #      '!'
>.                  #      newline
""")

bf.runCode()

2006年06月27日

日記

今朝ナカバヤシから製本された論文が届きました。昨日送ったメールにはまだ返事が来ていません。見事なまでのすれ違いです。(というか発送した時点で連絡くれればよかったのに)

Brainf*ckは、破壊しても構わないtemporary memoryをどこに置くのかの調整が重要ですね。使用期間が重ならない処理は同じ場所をテンポラリに使って構わないですし、テンポラリメモリの位置が離れているとステップ数も増えるのできれいに分けるよりも混ざっていた方が実行効率は高いですし。どのメモリがどの期間で使用されているかを理解して適切な位置にテンポラリを作ってくれるといいですね。

PythonによるBrainf*ckインタプリタ @ NISHIO HIROKAZU # Archived COREBlog。アーカイブのpreタグがもれなく1行とばしになってますね。やっかいだなぁ。そしてバグいりのインタプリタなので直したくなってきた、やばい、そんなことをしている場合ではない。


__ @柏

携帯の充電ケーブルを忘れてしまいました。まぁ、電話は明日すればいいか。

暑いですね。暑いけども、夜に冷房で体をこわさないように長袖を持ち歩かないと行けないのが面倒です。3年間通学をしてなかったので忘れてました。


__ 行きの電車の中で考えたことをメモしときます。 Brainf*ckは、本当の機械語よりも遙かにシンプルで、チューリングマシンよりは高級なので、名前さえ別のものだったら高校や大学の情報系の授業で使われていたかも知れませんね。「Brainf*ckのコードをいかにして生成するか」と考えていくと、過去のプログラミング言語の進化を追体験することが出来て興味深いです。

まず真っ先に考えたのは、アドレス位置の抽象化です。同じ「足し算をする」というコードでも、入力セルがどこで出力セルがどこかによって、コード中の「移動命令(「>」や「<」)」の個数が変わります。でもこれは本質的ではなく、アドレス位置に名前をつけて(add A B)と言うような表現をしても内部でAとBの位置関係から適切な個数の移動命令を生成することが容易に出来ます。擬似コードで書くとこう。

def move(A, B):
  "AからBへカーソルを移動する"
  before:
    assert cur == A
  do: (略)
  after:
    assert cur == B

次に、オブジェクトの生成と消滅に関して。create(A, n) と kill(A) が必要だと思います。

def create(A, n):
  "セルAの値をnにする。"
  destructive: [A] # 破壊されるセルのリスト
  before:
    assert A == 0
    assert cur == A
  do:
    return "+" * n  # 将来的にはもっと効率的な実装に変えることも可能だがとりあえずこれでOK
  after:
    assert A == n
    assert cur == A


def kill(A):
  "セルAを0にする。"
  destructive: [A]
  before:
    assert cur == A
  do:
    return "[-]"
  after:
    assert A == 0
    assert cur == A

説明が遅れましたが、before節の中でのassertはそのコードが実行される前に満たされているべき条件、after節の中でのassertはそのコードが実行された後に満たしているべき条件です。たとえばある命令のafterでcur == Aと宣言されており、その次の命令のbeforeでcur == Bが宣言されているなら、間に(move A B)を挟む必要があります。これは人間の頭を患わせなくても機械的に判断できますし、機械的に解決できる作業です。他にassert A == 0 というのもありますが、これが満たされていない場合には(kill A)を呼べばいいわけです。各命令は破壊するセルのリストを持っていますが、これは「その命令を包む命令」がセルを確保する場合には破壊されないセルを確保する必要があるからです。

さて、破壊の話が出ましたけど、Brainf*ckでの演算は基本的に破壊的です。関数型言語が副作用のない演算を追い求めたり、他の言語でもスコープを限定したりカプセル化したりして破壊を防ごうという努力がされてきたりしたのですが、基本はやっぱり破壊なのです。世界は破壊の中から生まれた(ぇ)

冗談はさておき、生成されたオブジェクトが演算のたびに破壊されるとなると、「破壊されたくないシチュエーション」で困るわけです。そういう場合に必要なのがcloneによるオブジェクトの複製です。

def clone(A, B, C):
  "セルAの内容をBとCに複製する"
  destructive: [A, B, C]
  before:
    assert cur == A
    assert B == 0
    assert C == 0
  do:
    return "[- (move A B) + (move B A) + (move C A)]"
  after:
    assert cur == A
    assert A == 0

たとえば足し算addは

def add(A B):
  "A+Bの結果をBに入れる"
  destractive: [A, B]
  before:
    assert cur == A
  do:
    return "[- (move A B) + (move B A)]"
  after:
    assert cur == A
    assert A == 0
と書けるわけです。ただ、この時点ではまだ「変数」はアドレスの別名でしかありません。しかも変数が指すアドレスが変化することはありません。掛け算のコードを書く際にこれでは不便で、それを解決するためにポインタの概念が誕生する瞬間を目撃してちょっと興奮していたのですが、言葉で説明しにくいですな。

とりあえず出勤途中の電車でメモ帳に手書きした内容はデジタル化出来たので続きは帰りの電車ででも考えることにしましょう。とりあえずアドレスのエイリアスとして生まれた変数はポインタへと進化する必要があるのが1点と、他のコードに副作用を及ぼさずに使うことの出来るテンポラリ領域を取得するための関数allocateが必要です。


__ 遅めの昼ご飯食べながら考えたのですが、Brainf*ckでエラトステネスの篩を実装するくらいはわざわざBrainf*ckを出力するプログラムを作らなくても作れそうな気がしますね。 どっちが大変なのかはよくわからないですけど、でも一度Brainf*ckジェネレータを作っておけばネタとして何度も使い回せそうです。Don't Repeat Yourselfですね。


__ 今日は携帯の充電器を忘れただけにとどまらず、上着も持ってくるのを忘れたようです。

はさみも持ってくるのを忘れました…。


__ 暑いけど席が冷房の直撃する場所なので冷房をつけると寒い。

帰りの電車の中で考えたBrainf*ckの続き。 とりあえず(move A B)は(move B)だけでいいですね。あと、セルが持ちうる値を「正の整数」とすると演算が閉じていないです。つまり0をデクリメントしたときに問題が起きます。そこで「整数」にすると今度はkillの実装が"[-]"ではダメになります。元の数が負の数の場合に問題が起きますから。でもそれでも別に頑張れば実装は出来るからいいのか…とか思ったのですが、WikipediaのBrainfuckの記事が正しければbyte型なので255をインクリメントすると0になる仕様だと考えるべきかも知れませんね。

Index of /brainfuck/compiled/winの実装では確かに255を超えた場合に0にリセットされてますね。でもこれメモリの内容を見る機能がないんですね、使いにくいです。

とりあえず今ちょっと昔書いたインタプリタをいじって、byteとかループのネストとかがきちんと動くバージョンを作ってみました。[]の仕様を誤解してましたね。英語版Wikipediaのプログラムが動いたので今回は正しいと思います。


__

>>> Move(frm = 3, to = 1).make()
'>>>[-<<+>>]'
>>> Move(frm = 1, to = 2).make()
'<<[->+<]'

class Move(Command): "Move(frm, to)" beforeCur = "frm" afterCur = "frm" destructive = "frm to" beforeZero = "to" afterZero = "frm" def do(self): result = "".join(["[-", Go(to = self.args["to"]).make(), "+", Go(to = self.args["frm"]).make(), "]"]) return result

寝ようっと。

2006年06月26日

キミならどう書く 2.0 - ROUND 1

100までの素数をエラトステネスの篩を使って列挙するプログラムを、Pythonで、defもifもwhileもforも使わずに1行(66文字)で作りました。以下はその作成過程のログです。


__ おおっと、今知りました。(via 竹迫さんの記事) キミならどう書く 2.0 - ROUND 1 - — Lightweight Language Ring 締め切りまであと30分しかないですね。うわー、もっと早く気づいていれば…。30分でPythonでdefもifも使わずに1行で素数を求めるなんて(勝手に問題を難しくしすぎ)

def foo(x): return [x[0] + [x[1][0]], [y for y in x[1] if y % x[1][0] > 0]]

あと29分!

>>> i = [[],range(2,100)]
>>> while (i[1] != []): i = foo(i)

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

とりあえず素数出た!ボーダーラインはギリ越えた! あと24分!whileを使わずにwhileを作るには…

>>> def foo(x):
	if x[1] == []:
		return x[0]
	else:
		return foo([x[0] + [x[1][0]], [y for y in x[1] if y % x[1][0] > 0]])

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

あと22分! ifを使わずに分岐をするには…

>>> def foo(x): return (x[1] == []) and x[0] or (foo([x[0] + [x[1][0]], [y for y in x[1] if y % x[1][0] > 0]]))

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

あと20分。うーん、再起を使ってしまうと関数定義で確実に1行使うので1行にまとめることが出来ない…。とりあえず時間がないから現状でコミットしてから考えるか…。

foo = lambda x:(x[1] == []) and x[0] or (foo([x[0] + [x[1][0]], [y for y in x[1] if y % x[1][0] >
 0]]));foo([[],range(2,100)])

関数定義をラムダ構文にして解決。


__ 改めてすでに投稿されているものを見てみると…ああ、Pythonでもっと短く作っている人が複数いる…orz。 時間がなくてじっくり既出コメントを読む暇がなかったのですよ、とイイワケ。 4つ目くらいの「圧倒的にPythonに不利な設定ですね!」を見て「そんなわけない!」と奮起したもので。

まぁ、負けてしまったのは仕方がないのでcoolな回答をピックアップしてみるとしますか。

[p for p in range(2,100) if 0 not in [p%d for d in range(2,p)]]

一つ目、なぜこれを思いつかなかったのかちょっと悔しいです。range(2,p)が「2以上p未満の整数」のリストなので[p%d for d in range(2,p)]が「「2以上p未満の整数すべて」でpを割ったあまり」のリストになります。その中に一つでも0があるなら、「2以上p未満の整数の中にpを割り切るものがある」、つまり素数でないということになります。 どれでも割り切れないものだけを残せば残るのは素数っていうわけです。シンプルかつ完璧。

filter(lambda i:reduce(lambda x,y: x*(i%y), range(2,i), 1), range(2, 100))

これも原理は一緒ですね。「2以上i未満の整数」のリストを作って、初期値1であまりを次々とかけていくと、もし0があるなら結果は0になるし、0がないなら結果は0にならない、というわけです。


__ まぁ、初戦は惨敗しましたが、二回戦以降があるならぜひ参加したいところであります。今度トラックバックする時はタイトルにPythonって入れます…。大あわてでトラックバックしたので割と見苦しいですね(´・ω・`)すみません。


__ せめてもの罪滅ぼし(?)に僕が書いたコードの「途中結果を関数への引数として渡す」という設計を見直して72行に縮めてみました。あとPythonインタプリタの直前に評価したものが「_」という名前の変数に入る仕組みを利用して代入も削ってみました。

lambda x:x and([x[0]]+_([y for y in x if y%x[0]]));_(range(2,100))

これでも66文字で、上で取り上げたcoolな解には3文字ほど負けているんですよね…。

自分が負けを認めたくないだけなのだと気がついたので勝ってそうな所で勝負してみよう。所要時間をチェック。

0.00555266102256
0.000577168327259

やった10倍速い。 これで満足して眠れます(笑)

バージョン管理

次のバージョンがbeta1.00なので、beta1.01、beta1.02…と上がっていって、安定版は2.0でbetaを外してリリースにするのはどうだろう。それ以降は安定版は2.01、2.02と上がっていき、開発版は常にbetaをつけてbeta3.00、beta3.01としよう。そうすれば「どれをダウンロードしたらいい?」という質問に「不安定でも機能がたくさんある方がいいのなら数字の一番大きいのを、ある程度安定したものがいいのならbetaのついていないものを」と説明するだけですむし。

参考文献: Open Tech Press | バージョン番号の衰亡

日記

おおっと、うかうかしていたら夏のプロシンの発表申し込みが終わっちゃってるじゃん。参加の申し込みは始まったところなので忘れないうちに申し込まないと。

前回、夜の懇親会でライフゲームの話題が出た際に多人数ライフゲームβなんてのを作ってましたとデモしたのだけど、結局1年間発展無しに放置していましたね。西尾泰和の日記(2006-03-09)でマップを大きくしたらどうだろう、と言っていますけど、やっぱこれ無理にAjaxを使うよりJavaアプレット使う方が素直な気がしますね…。

これのルールに関する考察は昔非公開のPukiwikiに書いたのだけど、どこにバックアップ取ったのやら…。公開していないとこういうときにググれないから不便です。

「ググる」を「ラ行五段活用」で単語登録したけど、「ググれない」はら抜き言葉で変換できない罠。


__ 何をどう間違えたのかカテゴリがGRINEditになっていました。

明日LL Ringのチケットを買わなきゃ。

博士論文がまだ出ていないと事務から電話がありました。博士論文の製本業者の手元にこちらから送った原稿が届いたのは1ヶ月以上前です。やれやれ。製本ができあがったら連絡が入るだろうと思って一時記憶から削除したのが間違いだったのでしょうか。毎週1回くらい進捗状況の問い合わせメールでも投げるべきだったんでしょうか。

とりあえず業者への問い合わせメールは出しました。事務への連絡は業者からの連絡が帰ってくるのを待つよりも、明日すぐ連絡して「業者に問い合わせています」と報告した方がいいだろうなぁ。


__ 区切り線の下についているアンカーはその区切り線から下の文章がその時刻以降に書かれたことを意味しないものとします、とどこかで宣言したい。ネット接続が出来ない環境で書いた文章を貼り付けるケースもありますから。


__ 「売りつくし」ののぼりが「つくし売り」に見えました。

「ツクシ売りの少女」というお話は、 貧しい少女が生活費を稼ぐためにツクシを売るのだけど誰も買ってくれなくて、 飢えに耐えかねて売り物のツクシを生のまま食べているうちに 生のツクシがもつ有害なアルカロイドの影響で幻覚が見え、急性中毒で死んでしまう、 というお話です。(捏造)

ツクシに幻覚作用があるかどうかは知りませんが、きっとこのお話の教訓は「食べられるものでも生で食べられるとはかぎりません」なのでしょう。ドングリ(シイの実)が食べられると聞いて、そこら辺のどんぐりを食べてしまった小学生の僕に聞かせてあげたい話ですね。


__ 木曜日に修理に出したデジカメは土曜日に修理完了の知らせが入り、日曜日はサポートセンターがお休みで、今日引き取ってきました。修理には1週間から10日程度見てくださいと言われていたのに仕事が早い。さすが松下。ナカバヤシとはえらい違いです。

1GBのSDカードって安いものは3000円しないんですねぇ。 高いものはすごく高いので512MBにしようかと思っていたんですが、 デジカメを修理に出した帰りにちょうど安い店を見つけたので そこで買ってしまいました。16MBから1GBになって撮影可能枚数が格段に増えました。 今までは容量節約のために800x600で撮っていたのですけど、 今度からは一番画素数の多いモードで撮影しても300枚も入っちゃいます。 動画も一番クオリティの高いので11分、 今まで通りのクオリティだと1時間以上撮れちゃいます。 そんなにバッテリーが持つのかどうかは知りませんが。

これで今までよりもっといい写真を作れるだろうと期待しています。 たとえば高感度モードにするとノイズが多くなりますけど、 基本的にモニターでしか見ないので縮小しますから、 そこで平均ではなくメジアンをとるアルゴリズムにしてみるとノイズが取り除けるんじゃないかとか。夢がふくらみます。


__ 論文書き。もうワードなんて大嫌いだー! TeXで書きたい! TeXに比べてワードはWYSIWYGなのがいいとする主張もあるけど、 10ptで印刷される文字は画面上では小さすぎます。 拡大すればいいんだろうけど面倒だなぁ。

ワードが嫌いだからといって、じゃぁTeXを他人に勧められるかというと それも微妙なところ。両方のいいところを兼ね備えたソフトが生まれてくれないかなぁ。

だいたい、Microsoft Officeみたいなバージョン感での互換性の低いもので原稿を提出させて大丈夫なのかなぁ。うまく行っているってことは大丈夫なのかなぁ。それともやっぱりうまく行ってなくて、中の人がいっしょうけんめい修正しているのかなぁ。


__ 明日は気分転換で柏に行こうかな。


__ 科研費で買えるものが、学校によってかなり違うことに衝撃を受けました。 たとえば、昨年度いっぱいで前の研究室から借りていたノートパソコンを返却するので新しいマシンを買う必要があり、 昨年度にいた大学では「10万を超えるものは備品」だったので 自費で今使っているノートパソコンを買ったのですが、今の大学では 「20万を超えるものが備品」なのでパソコンが買えてしまう、とか。もっともノートパソコンが2台あっても困るので買いませんが。

そしてさらに驚きなのが、今いる大学では「OfficeやWindowsは科研費で買えません(通常オフィスに備えてあるはずだから)」という決まりらしいです。いやはや。よくわからないけどOfficeを去年の予算で買っておいて良かったです。研究室のライセンスは卒業するときに返すべきだと思ったので自分用に買ったのです。どうせならWindowsXPのライセンスも買っておけば良かったかも知れませんね。

そしてどちらにしても「年度末までに1円残さず使い切ってください」というのは同じ。 まずこの制度を何とかしないと財政赤字削減とか議論しても意味がないよねぇ。 日本国中の、小は僕みたいな年間50万の小規模な予算から、大は省庁の予算まで、ありとあらゆる予算が、年度末になると予算を1円残さず使い切る為に無駄遣いを始めるわけですから。


__ 卵に黄身が2つ入っている確率がいくらぐらいなのか知りたい。 人間の場合は排卵誘発剤を使うと双子や三つ子が生まれやすくなるけど、 同じように鶏に排卵誘発剤を使うと黄身の複数入った卵が出来やすくなるのだろうか。


__ ATOKは使いこなすとすごく便利ですね。住所を打つのに「ちば[Tab][Enter]1ちょTAB[Tab][Enter]」であっさり入力できてとても幸せ。ただしいつまで経っても住所が覚えられないという罠w


__ おおっと、今知りました。 キミならどう書く 2.0 - ROUND 1 - — Lightweight Language Ring。頑張った結果: 西尾泰和のブログ: キミならどう書く 2.0 - ROUND 1

ふぅ。一応完敗ではない(苦しいいいわけ)


__ Brainf*ckでlookup tableではなくまじめに素数を計算したらどうなるんでしょうねぇ。 それをやるためにまず「Python→Brainf*ckコンパイラ」を作ってしまいそうです。睡眠時間がなくなってしまうので見なかったことにして寝ます。

2006年06月25日

日記

今日はだらけてるなぁ。


__ 新宿のジュンク堂に行ってきます。


__ 後輩と飲み。 やはりお酒を飲むと眠れなくなる傾向が強い。 もう28時だ。

2006年06月24日

Pythonでタブ区切りデータを出力する方法

毎回実装するのがさほど苦にならないので、ついつい毎回実装してしまったりするタブ区切りデータの出力ですが、やっぱりたまに改行をつけ忘れたりstrで文字列にするのを忘れたりすることがあるので、まとめてみることにしました。

class TSVFile(file):
	def write(self, v):
		file.write(self, "\t".join(map(str, v)) + "\n")

これは普通のfileを継承して、writeだけ独自のものに差し替えたクラスです。こうすると、以下のように普通のファイルを扱っている気分で、タブ区切りでの出力が出来ます。

fo = TSVFile("c:\\test.txt", "w")
fo.write((1,2,3))
fo.write((4,5,6))
fo.close()

ただし、タブ区切りじゃなくてカンマ区切りでもよくて、数字やアルファベットしか使わないというケースなら20 csv -- CSV ファイルの読み書きライブラリの利用も検討してみた方がいいでしょう。


__ 追記:writeを上書きしてしまわないで、writeListなどといった名前のメソッドを作るのがいいかもしれませんね。

Rで歪度や尖度を計算するには

Rで歪度や尖度を計算するにはe1071というパッケージをインストールすると楽。 インストール方法はRを立ち上げてinstall.packages("e1071")と入力すると パッケージをどこからダウンロードするかの選択ウィンドウが出るので(Windowsの場合)、 近そうな日本のサーバーを選択する。 library("e1071")とやってインストールされたライブラリをロードし、kurtosis(data)というコマンドでデータの尖度を計算することが出来る。歪度はskewness。

日記

エレキギターのピックアップ(弦の振動を感知する部分)って電磁誘導を使ってるんですね。鳴るほど♪楽器解体全書 エレキギターの音の原理。NHKで弦の端にピックアップがある場合と真ん中にピックアップがある場合の音の違いを実験していました。端にある方が倍音成分が多い音になるそうです。エレキギターも面白そう。 名前のわからなかった曲がパイプライン(音が出ます)という名前だと知りました。


_ _ 「学びてプログラミングせざれば則ち罔く、プログラミングして学ばざれば則ち殆し」と孔子も言っているわけですが(嘘)

SQLのクエリーは投げたことがあったけども、テーブル自体を自分で作ったことはなかったので、やっぱり作ってみて色々失敗に気づくことも。年月日ぞれぞれ「年」「月」「日」のカラムにしてしまった(元のデータがそうなっていたから)のだけど、これだと最新のデータを取得するのに"select foo from bar order by year desc, month desc, day desc"なんていう面倒なクエリーを投げないと行けない。投げる僕の方はさておき投げられるSQLiteの中の人は大変だろうな。「年や月に関係なく15日のデータを取得したい」なんてユースケースがあり得ないんだから、年月日まとめてcomparableなカラムを1個作っておいて、ついでにそれにインデックスをつけておけば中の人も楽ちんだっただろうに。

學而不編寫程序則罔 編寫程序而不學則殆。プログラミングってのは「程序(プログラム)」を編んだり寫(写)したりすることなのですか。程序は日程の程に順序の序と。なるほどねぇ。


__ Rで歪度や尖度を計算するには


__ てすと。 ふむふむ、spanでも十分ボタンっぽさをアピール出来ますね。凹んだりはしないけど。


__ Pythonでタブ区切りデータを出力する方法


__ 「暑くてしめっぽくて汗をかいたから」と思ってお風呂に入ると、体の表面が実は冷え切っていることに気がつきます。汗が蒸発せず、熱がこもってしまうのは、実は冷えて毛細血管が縮まっているせいなのかもしれません。梅雨や夏場に「暑くてしめっぽくて気分が悪い」という人はたくさんいても、温泉の洗い場で「暑くてしめっぽくて気分が悪い」って人はあまりいません。どちらかというと温泉の洗い場の方が湿度は高いのに。

防水ノートパソコンは高いのですけど、防水性と排熱を両立させるのが難しいのがなかなか商品化されない理由の一つなので、じゃぁ本体は外に置けばいいじゃないか、と思うのですよ。見える範囲にモニターがあって、手元に濡れても大丈夫なキーボードとマウスがあればプログラミングに支障はないかと。光る“ふにゃふにゃキーボード”が発売、英語版で2,000円とか、光る必要はないですけど手頃な値段で防水ですね。モニターは水のかからない程度に離れた場所で、一応ビニール袋にでも入れて口を縛っておけば大丈夫でしょう。


__ 逆もありかも。 つまり、 「プログラミングして思はざればすなわち罔し、思ひてプログラミングせざればすなわち殆し。」 3週間も前に「これで行けるはず」と思ったアルゴリズムを今やっと実装して試してみていて、 予想通りの結果も出るけども、入力データによっては予想外の値も出ることを知りました。 何か見落としがあったに違いない。 孔子 - Wikiquote


__ 運動がてら自転車に乗ってまだ行っていない方向に走ってきたのですけど、 大阪と違って隣の駅が遠いですね。1~2キロもあったので隣の駅に行って帰ってきただけで結構時間がかかってしまいました。


__ 2005年4月例会@物理教育実践交流会

プラスに帯電したシャボン玉と、マイナスに帯電したシャボン玉を浮かばせて近づけると、互いに激しく回転しながら引き合い、衝突して消滅します。

見たい。


__ デジタル一眼レフのレンズの部分をピンホールに変えるという手もあるようですね…。うーん。デジタル一眼レフを買うか…。その前に、とりあえず故障したデジカメは修理完了したらしいので、それを使って色々試してみてからにしたいと思います。今日、トレーシングペーパーに油を塗り込んで透明度を上げてたところですし。

そうそう、書き忘れてました。今までアルコールと油は混ざると思っていたのですけど、少なくとも飲めるアルコールと食用の油は混ざらないですね。もっと炭素の多いアルコールなら混ざるのかも知れないですけど。油を薄めようと思ってアルコールを入れたのに混ざってくれなくてがっかりでした。

地図を見て、職場のある島の西側は公園だと言うことを知ったので、今度は夕方の海を撮影してきます。


__ 自作ピンホールカメラ1号の内部を黒く塗装したり、光漏れが起きる部分をアルミ箔でふさいでいったり、いろいろな改良を加えています。問題はスクリーンの位置なんですけど、前回の写真を見る限りではピンホールからの光は十分スクリーンの端まで到達していますよね。あ、説明が遅れましたが、僕のピンホールカメラはピンホールからスクリーンに投影されたものをスクリーン背後からデジタルカメラで撮影する構造になっています。スクリーンをもっとピンホールに近づければより広い範囲がスクリーンに映るようになるのですけど、逆にデジカメの画面に移る映像は小さくなります。難しいところです。うーん。高画質モードで取って周りをトリミングするしかないかな。

デジタル一眼レフカメラは「デジタル一眼レフカメラレンタル」を使うという手もありますね。高いものだから色々試してみてどれを買うか決めるってのもいいかもしれません。


__ 部屋が全然片付きませんが、ハウスメイドのキャンディフルーツが20%割引キャンペーンをやっているのを発見してしまいました。うわー。悩む。


__ QRコードBlogを見て 「塗ると絵の出るQRコードって出来るのかなぁ」とか思ってしまった。


__ おおっ。ピンホールカメラのスクリーンを今までの半分くらいの距離までピンホールに近づけてみたのですが、 自分の部屋の照明を見ると肉眼でくっきり輪郭がわかるくらい明るくなっています。スクリーンまでの距離が半分になったのだから像の明るさは4倍になるわけですね。画角は大体40度くらいになったかと思います。一つの照明しか見えない状態では測りづらいですけど、目測で30度くらいには像が写りそうです。早くデジカメが帰ってこないかな。


__ アスペルガー症候群 - Wikipediaは割と充実してますね。ただ過度に賛美している意見がありますね。 多少公平性を欠くかも知れませんが、でも世間一般の認識はかなりお粗末なものですから、多少賛美されているくらいでもいいのかも知れませんね。難しいところです。3カ所ほど修正しました。

ADHD - Wikipediaはまだちょっと物足りないですね。


__ わお、もう26時。

2006年06月23日

日記

今日は調子が悪い。金曜日なので古新聞古チラシを収集場所に持って行き、燃えるゴミを出して、なぜかぼんやりしてしまいました。洗濯して干したはずの服はいったいどこへ行ったのだろう…とか。思いつくところを全部さがしてみたつもりなのにどこにもないし。謎。あと新聞をカバンに入れてくるのを忘れました。

JRの定期券を買いました。ややこしかったですけど。あとりんかい線の回数券を買おうと思ったのですが、財布の中にお札がないことが判明したので買えませんでした。今日の晩ご飯はsuicaの使えるところで食べないと行けませんね。

今月の前半はかなり論文を書く気をなくしていたのですが、やっぱり書いた方がいい気がしてきました。6月末締め切りですけど。Word指定ですけど。

「ICTスクール2006」のチューターをやるのですけど、学振の専念義務とのかねあいでややこしいです。週5時間のTAがOKなんだから単発6日間のTAもOKだと思うのですけど、後で怒られても嫌なので確認しないと行けないですし。去年まではTAは無条件でOKだったのですけど、今年から厳しくなった上に受け入れ研究者の承諾が必要になったので、万が一もめると先生に迷惑がかかります。最悪の場合でも、チューターの方をボランティアにするか、学振の方を1ヶ月中断するかすればいいと思うのだけどもね。


__ あー、論文書きたくない。正確に言えばどうせ書くのなら新しいGRINEditのことを書きたい。でもそれじゃ仕事とは認められないので仕方なく球面自己組織化写像による可視化の話を書く。


__ 【楽天市場】シーグランド クロスバー 800 の検索結果。同じ機種でも色が違うだけで40%以上値段に差が出るとは恐ろしい業界ですね。安いところは黒だけ売り切れています。

論文を書いたら自分へのご褒美で買おうと思っていたはずなのに、いざ安いのを見つけると在庫がなくなる前に買ってしまおうと思ってしまう罠。買いました。


__ 楽天ブックスの大見出し。コミック、写真集、雑誌、小説・エッセイ、ボーイズラブ。そ、そんな分類の仕方って…。


__ Polycomのリモート会議システムはカメラだけで128万もするようです。参考資料


__ 楽天ポイントの履歴によると、楽天市場での購入はポイントで買った場合でもポイントがつくようです。そして楽天カードで支払っているのでそちらにもポイントがつきます。つまり今のところ「楽天市場での買い物2%」>「Suicaでの買い物1.5%」>「楽天カードでの買い物1%」という状態ですね。後はEdyか。

Edyはさておき、楽天のポンカンシステムをまだ使ったことがないことに気がつきました。2ヶ月の間に楽天のシステムを3種類使うと、その2ヶ月に得られるポイントが2倍になる、などのシステムです。これで楽天カードのポイントまで2倍になると楽しいですよね。試してみる価値はあるかも知れません。

さすがにそこまで世の中甘くないようで「ポンカンキャンペーンの対象サービス以外は倍付け対象にはなりません」と明記されていました。カードのポイントが倍にならないのなら、特に必要ない安いものを買ってポイントを倍に増やす戦略も現実的じゃないですね。対象ポイントだけしか倍にならないということは仮に1万円のものを楽天市場で買ったとして楽天市場のポイントが100ポイント、楽天カードのポイントが100ポイントついている状態で倍付け達成しても+100ポイントになるだけ。楽天市場などで10万円使った場合は検討の余地もありますけど、楽天市場で10万円使うかなぁ…。

結局、ポンカンシステムは狙って達成しに行く必要はなさそうですね。

本を買うときは無批判にアマゾンを使っていたのですけど、楽天ブックスの方がいい場合もありますね。1500円以上の場合はどちらも送料が無料になるので、つくポイントの差で楽天の方が上ですし。安い場合も7月末までは楽天が送料無料キャンペーン中なのでやっぱり楽天の勝ちです。8月以降も楽天は250円でアマゾンは300円なのでやっぱり楽天の勝ち。アマゾンは古本が安い場合に有利ですね。

こうやってたいした額ではない金額を削り落としていく作業は、プログラムから余計な部分を削り落として高速化する作業に通じるところがあるから楽しいのかも知れません。


__ 今日発見した顔文字: (๑→ܫ←)。 各種顔文字の変遷をたどると進化系統樹が書けるかも知れません。

いや、違う。細菌同様、水平伝播が頻繁に起こるからツリーにならないに違いない。

文章中での出現頻度が低い文字でほとんどが構成されているような顔文字に関してはこの前作った隠れマルコフモデルのViterbiアルゴリズムで切り出せるはずですな。mixiの日記をいくつかの顔文字で検索して、ヒットした日記から過去にさかのぼりながら切り出していけば、特定宿主内でそれぞれの顔文字が占める割合がわかるはずですね。

あ、これは今はやりのメタゲノムじゃないか!(んなわけない)

とりあえず今はそんなことしている場合ではないのでこのネタは塩漬け。


__ 学振とチューターの話はやっぱりややこしそう。「アルバイトは週あたり5時間を上限とする」という文章が今年から規約(?)に導入されたのでダメみたいですね。でもいくら専念義務とは言っても1週間の休暇くらい取れるはずですし、休暇中のボランティア活動を禁止するような条項はどこにもない。アルバイトじゃないかと疑いをかけられた場合のことを考えてしかるべき立場の人に「アルバイトではなくてボランティア活動である」と書いてもらえばいいんだと思います。


__ 迷惑トラックバックが2件来ていた、という先日の話は事実誤認で、通算427件の迷惑トラックバックのうちMovableTypeのスパムフィルタが自信を持てなかったものが2件あると言うだけでした。いやはや、スパムフィルタのないブログなんか運営したら死にますね。


__ おなかすいたなぁ。土日はどうしようか。家の机は集中して長時間の作業すると腰が痛くなる椅子だけど、土日に集中して作業が出来てネットも出来るところってのもあんまりないよね。


__ バランスチェア 意外と安いですね。ちなみにこれは楽天アフィリエイトで生成したリンクなんですが、リンクの脇にサイズ1x1の小さな画像があります。これがクッキーを仕込むんでしょうかね。


__ 楽天カードが三井住友から楽天KCに変更になったようですね。最初からこういう戦略だったのでしょうか。巧妙ですね。三井住友の信用力を利用して囲い込んでおいて「8月1日以降の利用には楽天ポイントがつかないので楽天KCのカードに変更してください」とやってその囲い込んだ会員をごっそり引き抜くわけですね。うーむ。巧妙だ…。市場自体を手中に収めて売り手から手数料を取りつつ、カードローンで買い手からもお金を取るって訳ですな。僕はクレジットカードでお金は借りないので別に構わないのだけど。

ガーン。楽天KC発行の楽天カード限定で楽天市場での購入ポイントが2倍になるキャンペーンをやってる!今日買った分は三井住友だからポイントが倍にならない!ひどい!注文決定前に教えてよ!

カードの与信調査のフォームっていつも困ります。なんでこう、網羅されていない質問文なんだろう。仕事の種類が「お勤めの方、学生の方、主婦の方、年金の方」で「お勤めの方」を選ぶと「資本金の額」が必須です。おかしい…。こういうところに限って「その他」の欄がないし。勤務先の種類も、選択肢に宗教法人はあるけど独立行政法人はない。誰がこの選択肢を考えたんでしょう。この選択肢に答えることにいったいどういう必要性があったんでしょう。

2006年06月22日

日記

今日はいつもより1時間ほど早く朝の作業が済みました。何か忘れてるんじゃないでしょうか。

お弁当とお茶の用意をしたらいつも通りの時間ですね。 りんかい線は大手町を通っていることが判明。


__ デジカメは一応修理に出しましたが、有償になる可能性もあると釘を刺されました。まぁ、仕方ないですね。

秋葉原で見かけたX-CUTE クロスキュート - USBデジタルオーディオプレーヤーはあまりの小ささに笑ってしまいそうになりました。これで録音もできてしまうんだから怖い世の中になったものです(笑)

買おうかと迷っていたX-Bar XB800 クロスバーは店頭にはなくて代わりにXM002 X-mate クロスメイトが並んでいました。写真よりはキュートでしたが、150%高速再生の機能はなさそうです。

当初はボイスレコーダーを買おうと思って調べはじめたのですが「講演や議論を録音して後で聞き直す」なんてまめなことを僕がするのかどうかはなはだ怪しいと思うようになってきました。歩いているとかのメモが取りにくい状況でアイデアを記録するのにはこういうポータブルプレーヤーについているプアなマイクで十分そうですし、そう考えると「講演がしっかり取れるマイク」と「150%高速再生機能とデザインの良さと安さ」を天秤にかけると…うーむ。


__ そうそう、前に日記に書いた「はてなの広告はなぜ飲み物でもないのに『スポンサー ドリンク』なんだ?」という疑問は今「スポンサード リンク」だと言うことに気がついたので見なかったことにしてください(笑)


__ コメントで < を使うと、たとえ前後に空白文字を入れておいてもタグだと見なされて削除されているようです。そして&lt;にしてプレビューするとうまく行ったように見えるけどもテキストエリアの中はエスケープしていない < に戻っているのでうまく行ったと思って保存するとうまく行っていない罠。うーん。 今日はMovableTypeハックはしない。


__ 研究室に僕一人しかいなくてだいぶ寂しいんですけど。


__ M1の時の同期と飲み会。酔っぱらい。ビール1~2杯と日本酒2杯で酔っぱらうようになりました。かなり弱い。


__ 酔っぱらいごっこは楽しいです。具体的には、演歌っぽい鼻歌を歌いながら自転車で蛇行運転したりすることなのですが、でもよろめいて壁に膝をこすったのは事実なので実は「ごっこ」ではないのかも知れません。

2006年06月21日

物理演算の対象

剛体を実装しようかと思ったのですが、その前に物理法則をCommonGateway経由で操作できるようにした方がテストが楽ですね。

物理法則は「対象」を引数に取ります。たとえば「全頂点」であったり「全辺」であったり「anchoredな頂点」であったりします。これの「対象」の表現には「名前付きリスト」を使うとよさそうです。1つの「名前付きリスト」は1つの名前と複数のオブジェクトを持ちます。

頂点と辺の区別は重要ではないのかも知れません。現状で頂点リストと辺リストを分けて管理していること自体が不必要に具体的であるとも考えられます。でもそこまで抽象化するのは、抽象化するニーズが生じてからにした方がいいかと思います。過度の抽象化によってパフォーマンスが劣化しても仕方がないですし。

地球シミュレータが排出するCO2の量

地球シミュレータがどの程度の量のCO2を排出しているのか気になったので計算してみました。

地球シミュレータ開発の現状(PDF)によれば1つのノードで8kVAだそうだから、640台で5120kVAです。ほとんどの電力はCPUで消費されるだろうからこれはほぼ5120kWと見なして良い、という考えで正しいのでしょうか。24時間稼働しているので1日の消費電力は24倍して122880kWh。中部電力 | 新エネルギーデータ - 発電方式別CO2排出量によれば1kWhを石油火力で発電すると742gのCO2が発生するようなので一日あたり91176960gのCO2が発生する。つまりおよそ91.1トン。えー、そんなに多いの?計算間違ってない?日本のCO2排出量 によれば2000年度の日本のCO2排出量は12.7億トンなので地球シミュレータは日本の全CO2排出量の0.0026%を占める。仮にCO2排出量を1億人に均等に割り当てたとしたら地球シミュレータだけで26万人分を排出する計算に。これでもまだノードの消費電力だけで、それによる発熱を冷やすための空調や、照明や、その他もろもろは計算に入っていないのだけど…。えっと、1日あたり91.1トンのCO2が排出されるという計算が正しいとして、91.1トンとはどれくらいなのか、というのも計算してみましょう。排出権取引を活用したCO2フリーガソリン企画によれば「クルマ1台で1か月に120リットルから130リットルのガソリンを使います。ガソリン1キロリットルあたりの二酸化炭素排出量は2.3トンです。」とのことなので91.1トンのCO2を出すガソリンの量は39.6キロリットルです。それは月に125リットルのガソリンを消費する車で317台分。と言うことは30倍して、9510台の車が1日に排出するCO2と地球シミュレータが1日に排出するCO2の量が大体同じ、ということですかな。

日記

雨なのであまり光が強くないですけど、夜の電灯よりは明るいことを期待してピンホールカメラで撮影。

pinhole
pinhole posted from フォト蔵

一応、絵にはなるようです。

pinhole2
pinhole2 posted from フォト蔵

しかし、ここで悲