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

2006年07月30日

日記

実家の鍵を持って帰るのを忘れたので割と動きづらい。

部屋はもうものすごい変わりようで、工事中のため廊下は土足だったりという状況。 そんなわけでPHS接続。

ゲド戦記4巻読了。劇場版のCMに出てくる女の子は4巻の主人公のテルーなのかなぁ。でもあんな大きな声ではっきり物を言う子じゃないんだけどな。5巻あたりで成長してはっきり物を言うようになるのかな。そして、3巻までは「子供に読ませたい本」だったけども、4巻は小学生時代の僕では理解できないのではないかと…力を手にして上り詰めた男が力を失った後の苦悩とか、熟年の恋とか、虐待を受けた上に火の中に捨てられて顔にケロイドのできた女の子とか、ちょっと小学生には重たすぎるような。小学生の時にあえて重たいのを読んでおいて、成長してから改めて読んで再発見するのがいいのかもしれないけど。

Rubyでオブジェクトのメソッド一覧を取得する方法を覚えたので 勉強が格段に進みやすくなりました。 やっぱリフレクションは重要ですね。 プログラミング初心者にプログラミングを教える際に 最初に教えるべきことはリフレクションなのではないでしょうか、 と煽ってみる(誰を)

ハッシュとかをto_sしてもべったり張り付いた見にくい文字列を返すので (なんでそんな文字列を返したいのか謎) 見やすい文字列を返すメソッドも絶対あるはずだと思ったのでした。 そしてそれはirbとかで評価したオブジェクトを表示するのに使われているはずで、その為にすべてのオブジェクトがそのメソッドを持っているはずだ、 と思ったのでメソッドの少なそうなnilのメソッド一覧を見ていたのでした。 目的の物はinspectですね。

どうしてRubyには同じ意味で違う書き方の物がいっぱいあるんだろう。 procとlambdaとか。実は微妙に違う意味なんだろうか。


__ 「ICTスクール2006」の実施及び参加高校生の募集について-文部科学省。そんなこんなで吹田にいます。

prototype.jsについてきたJavaScriptコンソールを複数行打ち込めるように改造してみました。

Avid Free DV

Inkscape. Draw Freely。なんかスクリーンショットにフラクタルなものがあるのでスクリプティングができるのかと思ったら

For file input/output, special features, etc. Inkscape is able to tie into external programs. Create new .inx files to hook these up for use in Inkscape. Also, if you're comfortable scripting in Perl, Python, etc. have a shot at improving the extensions, too!

だって!

2006年07月29日

日記

Rubyでは1 / 0.0 が Infinityというものになるみたい。1 / 0.0 * 0.0 は NaNになりました。Infinity - InfinityもNaNになるみたい。つじつまはあってそうですね。

DELLノートまた炎上 - Engadget Japanese。また燃えたのか…。何が原因なのかはっきりしないと怖い。とりあえずノートパソコンで重い計算を走らせたまま寝るのはやめた方がいいのだろうか?

高校生をインスパイアするためにいくつか本を持っていって「自由にお読みください」と置いておくことにしているのだけど、今回は東京からだから重い本を持って行くのは辛いなぁ。OS自作入門とか…。まぁ、興味のある人は本屋で見ることができるだろうから、本屋で見ることのできない物を主体にするか…。プロシーディングとか。日本顔学会誌、感性的ヒューマンインターフェース公開シンポ、第46回プログラミングシンポ(マンガの載っている論文誌)、ことば工学研究会、別冊数理科学 生命を作る、ComputarToday 神経情報処理最前線、あと自分の論文別刷り。うーん、アカデミックに偏りすぎているけど、OS自作入門は1冊でこれ全部より重いし…ふつうのHaskellを持って行っても高校生にはうけなさそうだしなぁ。あ、人工知能学会のボードゲーム「研究する人生」は受けそうだ。でもラボに置いて来ちゃった…。

もう14時だ。あるとよさそうな物を考え続けてないで、大阪行きの新幹線に乗るべきだ。完璧な準備は不可能だ。 GO!

Just Another Python Hacker, その2

>>> print (lambda a,t,g,c:''.join([chr(x)for x in[g-t-c*t&a,a&a*-a/g,a-c&a,g/t+a
-c&a,t*g&t,-a*a&a-t,-g-a%g*t&a,a+a*a*g&a,g/t+a-c&a,a&-c-c,g/c^g+c&g-c,a^a&c-a,t*
g&t,g&t-g-g,t+a+a+a+t&a,g/t+a-c&a,a&-c-c,a+a*a*g&a,-g-a%g*t&a,t*g&t,g+g%-c&a,g-a
+g&a,a^g*a+c&a,a&c-a-t%c-g,g/c^g+c&g-c,a^a&c-a,g%c*t-c&t]]))(*[ord(c)for c in un
icode('西尾泰和','sjis')])
Just Another Python Hacker,

自分専用JAPH。デフォルトエンコーディングの設定をきちんとやればエンコーディング指定の'sjis'はいらなくなると思います。ちなみにバイオに詳しくない人のために説明すると、ATGCは人間の遺伝情報を構成する4種類の部品の頭文字です。

ソースコードは、自分の得たい物が得られてしまうと他の人のために読みやすくしたりバグを取ったりするモチベーションがなくなるのでうまく動くかどうか知りませんが、一応公開しておきます。フォーマット文字列を使わないで西尾泰和の日記(2006-02-02)と同じ方法を使えばもっと短く書けたかもしれませんが…まぁいいや。


__ 追記。大文字の方がいいかも。

>>> print (lambda A,T,G,C:''.join([chr(N)for N in[G-T-C*T&A,A&A*-A/G,A-C&A,G/T+A
-C&A,T*G&T,-A*A&A-T,-G-A%G*T&A,A+A*A*G&A,G/T+A-C&A,A&-C-C,G/C^G+C&G-C,A^A&C-A,T*
G&T,G&T-G-G,T+A+A+A+T&A,G/T+A-C&A,A&-C-C,A+A*A*G&A,-G-A%G*T&A,T*G&T,G+G%-C&A,G-A
+G&A,A^G*A+C&A,A&C-A-T%C-G,G/C^G+C&G-C,A^A&C-A,G%C*T-C&T]]))(*[ord(N)for N in
unicode('西尾泰和','sjis')])
# -*- coding: cp932 -*-
#
# Just Another Python Hacker,
#
queryStr = "Just Another Python Hacker,"
query = [ord(c) for c in queryStr]

targetStr = "西尾泰和"
seeds = [ord(c) for c in unicode(targetStr, "sjis")]
print seeds

needs = []
for q in query:
    if not(q  in needs):
        needs.append(q)


caches = [{}]
numOp = {}
for i in range(4):
    caches[0][seeds[i]] = str(seeds[i])
    numOp[seeds[i]] = 0

def applyOpBuilder(c):
    def applyOp(p):
        return "%%s%s%%s" % c % p
    return applyOp

def applyOpBuilderInvert(c):
    def applyOp((x, y)):
        return "%%s%s%%s" % c % (y, x)
    return applyOp

operators = [applyOpBuilder(c) for c in "+-*/&|^"]
operators.extend([applyOpBuilderInvert(c) for c in "-/"])
operators.extend([applyOpBuilder(s) for s in ("%%",)])
operators.extend([applyOpBuilderInvert(s) for s in ("%%",)])

def evalAndCache(eq):
    try:
        v = eval(eq)
        if numOp.has_key(v):
            return
        if v < -50000 or 50000 < v:
            return
        numOp[v] = level
        eqs[v] = eq
        if v in needs:
            needs.remove(v)
    except Exception, e:
        print eq, e

try:
    for level in range(1, 100):
        print level
        eqs = {}
        for eq in caches[level - 1].values():
            evalAndCache("-%s" % eq)

        for i in range(level):
            j = level - i - 1
            if j < i: break
            for a in caches[i].values():
                for b in caches[j].values():
                    for f in operators:
                        eq = f((a, b))
                        evalAndCache(eq)
                        if needs == []:
                            caches.append(eqs) 
                            raise "Finished!!"



        caches.append(eqs)
except:
    data = "''.join([chr(x) for x in [%s]])" % ",".join(
        [caches[numOp[q]][q] for q in query])
    for i in range(4):
        data = data.replace(str(seeds[i]), "atgc"[i])
    print "print (lambda a,t,g,c:%s)(*unicode(targetStr, 'sjis'))" % data

2006年07月28日

プログラミング教育に関する考察

やろうと思いついけば1分で出来ることでも、やろうと思うまでは勝手には出来上がらない。作る技術も大事だけど、作ろうと思うことのほうがもっと大事。

大学や高校でかなりの人数にプログラミングを教えているはずなのに、プログラムを書ける人がこんなに少ないのは、「作ろうという思い」不在のまま「作る技術」だけを教えるからなんだ。僕のプログラミング演習ではそこんとこを何とかしたい。でも、モチベーションってのは教えたり与えたりするもんではないからなぁ。難しい。

2004/06/01 01:25:40の僕はこんなことを思っていたようです。今の僕なら「「作ろうという思い」不在のまま「作る技術」だけを教えるからではないだろうか。」と書くかもしれません。

渡辺さんの日記の「プログラムをゼロから教えるには、どんな形式で何コマかけてどこまで教えるべきだろうか。」という文章を読んでからいろいろなことを考えていますが、あまりまとまっていません。

もちろん、「作りたい物を作ることのできる」プログラマを育てるのなら、時間はたくさんあった方がいいのですが、現実的にはそんなにたくさんの時間を割くことができません。教える教師も、それなりに高いスキルを持った人間が一貫して教えるのが好ましいですが、結局のところプログラミングの専門家でも教育の専門家でもない、研究の専門家が片手間に教えることになる場合が多いかと思います。一貫して教える人を用意できなくて、複数人で持ち回りになったりするケースもよくあることです。

そして、やはりみんな「プログラミングは授業なんかで説明したって書けるようにならない、自分で手を動かして実装しないと」と思っているのでしょう、課題がたくさん出るわけです。 プログラミングの課題は、できる人にとっては軽い課題でも、できない人にとっては100倍もの負担となってのしかかります。半ば必然的に、「できる人」の書いたソースコードが出回り、できない人がそれを読解して改造して提出するというケースが出てきます。

「できる人」のソースコードや説明が、教師の作った講義資料よりもよいものなのであればそれは歓迎してもいいことなのかも知れませんが、そうとは限りません。学生たちは「ちょっとできる学生」が書いた「あまりよくないわかりにくいコード」を、それが課題の回答だからという理由で一生懸命読むかもしれないわけですよね。たとえそのコードに変数名の綴り間違いがあろうが、使われていない関数があろうが。

「コードを書いて、コンパイルエラーが取れて、実行したら期待した結果が出た」というのはゴールではないですよね。でも、現状の課題は「どんなに汚くても、人からのもらい物で中身を理解していなくても構わないから、とりあえず動く物を作る」という課題ではないでしょうか?そんな課題ではどんなにこなしてもプログラマは育たないのではないでしょうか。 僕自身は、大人数を相手に教えたことはないので、そういうシチュエーションでは実現不可能なことなのかも知れませんが、「とりあえず動くコード」を「わかりやすいコード」や「より高速に動くコード」に変える作業が抜けているように思います。生徒が自分で考えて作った「もつれたスパゲッティ」を、解きほぐして整理し、わかりやすくすることが必要なのではないでしょうか。

可能ならば、課題の提出が早い人にインセンティブを与えて「できる人」のコードを締め切り前に入手し、それを添削した上で無記名で公開してしまうというのがいいかもしれませんね。誰がその「添削」という労力を払うのかが難しい問題ですが。考えれば考えるほど、プログラミングの授業を1対多でやるのは難しいような気がしてきます。1対3くらいならまだなんとかなるかも知れませんが…。ううむ、そうか、僕が今まで教えてきたのは、全部最終的には1対1で目の前でコーディングしたり、できあがりのソースをメールで送らせてがりごり改良して送り返したりしているなぁ…。1対多には応用できないかも…。

思い出すことのできるメモに関する考察

過去の日記を読んでいて、今でも重要だと思える内容があったので転載してみました。2004/06/19 10:17:05。

以前どこかの大学の講演がストリーミングで視聴できるようになってるのをBGMにしてたな。と思い出して探す探す。 http://www.stanford.edu/class/ee380/

人間の記憶力は当てにならないからこそ、日記などの形で記録をとることと、 それを検索できるようにすることは重要なわけですがね。 いい方法ないもんですかね。 横着プログラミングを参考にしつつ考える。

僕は2001/4/29 12:3:35から2003/8/13 16:17:35までの間に2630個、3MB弱のメモを書いているのだけど、 現在の技術でこれを全文検索するのはちっとも難しくない。 今後も僕が書くメモは増え続けるだろうが、 メモの量の増加よりコンピューターの性能の向上のほうが早いだろうから、 今後も検索が容易であることは変わらないだろう。

一つ目の問題点は、「探す」ことは出来ても「思い出す」ことが出来ないことだ。 文字の発明によって、記憶の外部化が可能になり、 さらにその電子化によってその外部記憶の中から「探す」ことも容易になった。 しかし、「ふと思い出す」ということは出来ない。 このストリーミング放送にしても、今「以前、どこかの大学の講演をストリーミングで聴いていた」 という内部記憶を「ふと思い出した」からこそ外部記憶からそのURLを探し出すことが出来たのだ。 4月の頭から「英語力を鍛えなきゃ」と思っていたにもかかわらず、 「思い出す」のに80日もかかったことになる。

もう一つの問題点は、このメモの低水準さだ。 人間の脳の中のアイデアは、イメージが連想でつながりあったシーケンシャルでない形であって、 それを声という1次元的なデバイスに出力するために、 シーケンシャルな文章という形にコンパイルする必要性があったわけだ。 しかし、文字を使えばより高水準な表現手法が可能であって、その一つに 人生に奇跡を起こすノート術―マインド・マップ放射思考 のような脳内の連想を書き出す方法があるわけだ。 メモも、このような、より高水準な形で書き、高水準な形で検索が出来るようになって欲しいのだけど、 残念なことに電子的に高級なメモを書いたり検索したりする手法はまだまだ発展途上なんだよね。

フロー状態で文章を書くときって、 次から次から思いつく内容をそのまま文章の形で出力していくわけだが、 これってのは本来放射状の「マインドマップ」をシーケンシャルにたどっているものなわけなんだよね。 過去の日記を見れば、似たアイデアをいろんな文章で書いているんだが、 これがシーケンシャルなせいで容易にマージできない。 そこんとこなんとかならないものか。

とかとか思ったりもするんだけどまとまらないなぁ。 とりあえず、古いサーバーではNamazuを入れて全文検索できるようになっていた日記だけど、 今のサーバで書いてあるのは検索できないので後々不便に違いない。 そのうちに何とかしないと。 適切な形でエクスポートするのが一番手間が少ないだろうなぁ。むー。

高水準言語でメモを取る話に関しては、 どうせみんな読まないし(ぇ) 個人用のメモとして適当に実装してみるのも悪くないような気もする。

マインドマップをマインドマップの形のままやりとりしたり保管したり検索したりできるようになると、新しい世界が開けるのではないかと思います。

日記

PythonでWikiを作りかけたけども、やっぱり面倒だからPukiwikiを使おうかと思います。 reStructuredTextを使うとツリーとして扱うのも簡単だけども、別にツリーとして扱わないといけないほど複雑なことをするわけでもないですし。

大まかに説明すると「言語XでDxと書くことでできる処理は言語Yではどう書くのだ?」という質問に答えを出せるようなサービスを作るためには、言語Xで書かれたDxというコード片と言語Yで書かれたDyというコード片の対応付けが必要です。この対応付けは自動的に行うことが困難だと思われるので、何らかの形で「人がそれを入力することのできるシステム」が必要です。

あと、おそらくコード片の規模は数文字という訳にはいかないと思います。異なる言語のコードはそう簡単に対応づけられません。たとえばオブジェクトを文字列化するPythonのコードはstr(o)ですが、これはオブジェクトoが持っているメソッド__str__の呼び出しと同じなのでo.__str__()と書くこともできます。またこれに「オブジェクトの文字列化」という意味で対応するJavaのコードはo.toString()ですけど、「整数を文字列化」という意味で対応するのはString.valueOf(o)ですよね。これはJavaがオブジェクトとオブジェクトでないものの両方を持っているからなのですが、こういう個々の言語の仕様は知らなくても目的の物にたどり着ける設計が好ましいです。 そう考えると「いくつかの短めのコード片+簡単な説明」くらいの規模を単位にするのがいいと思います。

Wikiでそういうコード片の対応付けを収集しておいて、たとえば「Pythonの無名関数lambdaみたいなのをRubyで書くにはどうするんだ?」と思ったら、Pythonに関する記述の中からlambdaを検索して、対応するRubyの項目を読む、と。Pythonコンテキストに限定して検索することさえできるようにすればこういうことができるはずですし、コンテキストの限定も簡単に考えれば単にその部分だけ切り出して置いてその中から検索すればいいだけなので難しくありません。


__ とりあえずPythonでフラクタル(ジュリア集合) @ NISHIO HIROKAZU # Archived COREBlogとかで画像がリンク切れになっていて台無しだったのをなおしました。古いサーバのcoreblog/imagesにあったファイルを全部新しいサーバにアップし直し。あと古い日記の中からピックアップをすると「できたできた」系の「中身を表現していないタイトル」に怒りすら感じます(ぇ)

古い記事はwgetして新しいサーバにアップするだけでも構わないけども、修正の楽さなどを考えるとピックアップした物だけこのBlogに貼るのがいいのかも知れない。Zopeからエスクポートしたzexpファイルと、この前後輩に送ってもらったExtentionの中身のzipファイルと、ついでにwgetでHTMLにした物を作ってどこかにきちんとバックアップしておけばいいはず。

いちおう、プログラミング言語シソーラスの為のWikiを作ったけど、すぐ公開するか、ある程度中身が溜まってから公開するか悩みどころ。中身が溜まってから公開することにしたんだけども、どれくらい溜まったら公開するかも悩みどころ。Rubycoの日記を全部読み終わったら公開するかな。


__ 帰りの電車で思いついて変な物を作ってしまいました。Just Another Python Hacker, その2


__ 豚皿の中くらいのを買って帰ったらご飯が一合食べられてしまった。今度から小さいのにしようっと。

2006年07月27日

PythonとRubyでパスカルの三角形ワンライナー

rubyco(るびこ)の日記 - 呼び出し側のアスタリスクを読んで、「あ、そうか、それを使えば頭から二つずつ取ることができるか」とGame Scripting Memo - 続・パスカルの三角形のことを思い出しました。

>>> def get2(f, a, b, *rest):
	result = [f(a, b)]
	if rest:
		result += get2(f, *rest)
	return  result

>>> from operator import add
>>> def dup(aList):
	return reduce(add, [[v, v] for v in aList])

>>> dup([1,2,3])
[1, 1, 2, 2, 3, 3]
>>> def sandwich(bread, meat):
	return [bread] + meat + [bread]

>>> sandwich(0, dup([1, 2, 1]))
[0, 1, 1, 2, 2, 1, 1, 0]

>>> get2(add, *sandwich(0, dup([1, 2, 1])))
[1, 3, 3, 1]

とりあえずワンライナーにするために手を加えて…

>>> def get2(f, a, b, *rest):
	return rest and [f(a, b)] + get2apply(f, *rest) or [f(a, b)]

>>> def next(xs):
	return get2(add, *sandwich(0, dup(xs)))

>>> def next(xs):
	return get2(add, *sandwich(0, reduce(add, [[v, v] for v in xs])))

>>> def next(xs):
	return get2(add, *[0] + reduce(add, [[v, v] for v in xs]) + [0])

>>> next([1])
[1, 1]
>>> next(_)
[1, 2, 1]
>>> next(_)
[1, 3, 3, 1]
>>> next(_)
[1, 4, 6, 4, 1]
>>> def next(xs):
	g = lambda f, a, b, *rest: rest and [f(a, b)] + g(f, *rest) or [f(a, b)]
	return g(add, *[0] + reduce(add, [[v, v] for v in xs]) + [0])

>>> def next(xs): g = lambda f, a, b, *rest: rest and [f(a, b)] + g(f, *rest) or [f(a, b)]; return
g(add, *[0] + reduce(add, [[v, v] for v in xs]) + [0])

>>> next([1])
[1, 1]

いちおうワンライナーになりました。

>>> lambda xs: (lambda g: (lambda *args: g(g, *args)))(lambda g, f, a, b, *rest: rest and [f(a, b)] +
 g(g, f, *rest) or [f(a, b)])(add, *[0] + reduce(add, [[v, v] for v in xs]) + [0])
<function <lambda> at 0x0146BC70>
>>> _([1, 2, 1])
[1, 3, 3, 1]

これで文を使わない1つの式になりました。


__ Rubyは詳しくないので…ええっと、Proc.new{|x| x + 1}で無名関数のようなものができて、callでそれを呼べるんですかね。あ、 proc {...} で Proc.new{...} と同じだそうです。


$g = proc {|a, b, *rest|
	if rest.size == 1
		[a + b, rest[0]]
	else
		[a + b] + $g.call(*rest)
	end
}


(0..9).inject([1]){|xs, item|
	proc{|x| p x; x}.call(
		$g.call(0, *xs.map{|v| [v, v]}.flatten)
	)
}

三角形の頭が表示されないですけど一応動きました。


__

(0..9).inject([]){|xs, i|
  proc{|x| p x; x}.call(
    if i == 0
      [1]
    else
      proc{|xs|
        proc {|g|
          proc {|*args|
            g.call(g, *args)
          }
        }.call(
          proc {|g, a, b, *rest|
            if rest.size == 1
              [a + b, rest[0]]
            else
              [a + b] + g.call(g, *rest)
            end
          }
        ).call(
          0, *xs.map{|v| [v, v]}.flatten
        )
      }.call(xs)
    end
  )
}

できました。改行を取り除くのはお任せします。

PythonとRubyでデフォルト引数の評価されるタイミングは違う

驚きました。 rubyco(るびこ)の日記 - デフォルト引数は明示的に評価されると同じことをPythonで書いた場合、関数定義の時点で評価されます。

>>> def default(n):
	print "default", n
	return n + 1

>>> def foo(x, y = default(5)):
	print x, y

	
default 5

Rubyでは関数が呼ばれた時にデフォルト引数を評価するようです。しかも遅延評価とかではないようで、何度も関数を呼べば何度も実行されます。つまりPythonで書けば

>>> def foo(x, y = None):
	if y == None: y = default(5)
	print x, y

に相当する状態のようです。

Pythonで特定の何種類かの値からランダムに選んでリストを作る方法

勝手にどう書く0.0を読んで、勝手に抽象化しました。

>>> from random import choice
>>> [choice([0, 1]) for i in range(10)]
[1, 0, 1, 0, 0, 0, 0, 0, 1, 1]
>>> [choice("ATGC") for i in range(10)]
['C', 'A', 'C', 'G', 'C', 'C', 'T', 'G', 'C', 'C']

choiceは与えられたリストからランダムに選ぶ関数です。研究がゲノム関係だったので、ランダムなゲノム配列を作るのに重宝しました。

日記

だいぶわかってきた。「脱いだ服を床に散らかさない」は「~しない」だから「具体的に実行可能な行動」ではない。「脱いだ服をきちんと片付ける」は「きちんと」が定義されていないのでやっぱり「具体的に実行可能な行動」ではない。「脱いだ服は洗濯機の上の籠に入れる」ならOK。次に「服を脱いだら(即)籠に入れる」だと、籠に入っていない服が見つかったときに「失敗」になって無力感を味わうのだけど、「脱いだ服は籠に入れる」なら籠に入っていない服が見つかったときにそれを籠に入れて「成功」させ達成感を味わうことができる。

「毎日○○する」は1日失敗するだけで達成不可能になる。だから三日坊主になりやすい。「できたら○○する。○○した回数を数える」なら1回1回達成できる。とりあえずもうすぐ13時になるのに家でこんなことを書いている僕は「午前中にラボに行く」を目標にした方がいいかも。でも金曜から大阪だしなぁ。

「Rubyを勉強する」は具体的に実行不可能なので、「rubyco(るびこ)の日記を読む」にすれば…と読み始めてしまった。だからラボに行くのが先だって。冷房のついている部屋から出て駅まで行くのが無意識の足かせになっている。というか11~13時に出勤するので余計暑い。もっと早く行けばそんなに暑くないはずなんだけどね。

西尾泰和のブログ: PythonとRubyでデフォルト引数の評価されるタイミングは違う

よし、出かけるとするか。


__ ラボに来たけど誰もいない…。

Rubyはメソッド名に?や!を使えていいなぁ。以上以下があっていいなぁ。

下の二つは同じことなのかなぁ。

class Foo
    def Foo.bar
    end
end

class Foo end def Foo.bar end

全部が大文字じゃなくても、頭が大文字なだけで定数になるのですね。

しまった、もう5時半。何してるんだ自分。(Rubyの勉強?)


__ なんだか、4月の終わりにYouTubeが仕様変更をしたので昔僕が作ったダウンロード用スクリプトは使えなくなったそうです。新しい仕様では、tとlというパラメータが埋め込んであるので、何らかの方法でそれを取得しないといけません。

とりあえずダウンロードするスクリプトを書いてみたのですけど、ファイル名にタイトルが埋め込まれるようにしたらWindowsではUTF-8のままで書くと化けてSJISで書くと読め、Macではその逆。うーん。MacのFLVプレイヤーは知らないしWindowsで見るならSJISで出力すべきか。MacのPythonでSJIS出力をしようとするとSJISなんてエンコーディングは知らないと怒られたのでJapaneseCodecsをインストール。あー。MacでSJISのファイルを作成しようとしたらIOErrorになっちゃった。何か良くない文字でも含まれているのかな。仕方がない、urllib.quoteで変換しておいて、後で元に戻すとします。

さて、これで特定のキーワードで新しく見つかったまだダウンロードしていない動画を全部ダウンロードするスクリプトができたので、cronか何かで定期的に走らせればラーメンズのコントをもれなく自動的に収集できるはずです。


__ rubyco(るびこ)の日記 - マルチリンガルなシソーラス検索。欲しいなぁ。でも、データファイルを誰が整備するのか、を考えるとWikiを使ってデータ収集する方がいいのかも。Wikiに同じ内容のコードをいろいろな言語で書くと、その例えばPython部分のコードは"mltfind_python"という文字列がどこかに埋め込まれたページに出力され、同じ内容のコードをRubyで書いたページなどへのリンクが張られる、と。簡単にできそう。あー、でもその場合の問題点はGoogleがたとえ引用符で囲っていても"string->list"をstringとlistに分けちゃうことか…。検索をGoogleに丸投げではダメってことか…。 勝手に区切ったりしない全文検索を使うべきなんだろうなぁ。記号だらけだから。

帰ってきました。おなかいたい。

適当なWikiを改造したら簡単だ…と思ったのですけど、適当なWikiってどれでしょう…。うーん。大した機能は必要ないので作る方が手っ取り早いのかも。とりあえずDocutils: Documentation Utilitiesをインストールしてみました。reST rendererのソースがこれ。短い。

出力されたHTMLから正規表現で切り出したらいいと思っていたけども、ツリーで扱うことも簡単にできました。

XREA.COMにはdocutilsが入っておらず、docutilsを全部コピーしてみたけど「romanをimportできない」と怒られました。やれやれ。

あ、roman.pyだけdocutilsの中じゃなくてsite-packagesの中にありました。コピーしたら動きました。pywiki_0.01.py reStructuredTextを試せますが、書き換え保存はできません。

ここまでは簡単だったけど、編集がかぶったときの処理とか考えるの面倒だなぁ。


__ 4.4 difflib -- 差異の計算を助ける

タイミング: 基本的なRatcliff-Obershelpアルゴリズムは、予想の3乗、最悪の場合でも2乗となります。SequenceMatcher オブジェクトは、最悪のケースに比べて4倍、予想される挙動は、シーケンスの中にどのくらいの要素があるのか(最良なのは一列の場合)、というややこしい状況に依存しています。

4.4 difflib -- Helpers for computing deltas

Timing: The basic Ratcliff-Obershelp algorithm is cubic time in the worst case and quadratic time in the expected case. SequenceMatcher is quadratic time for the worst case and has expected-case behavior dependent in a complicated way on how many elements the sequences have in common; best case time is linear.

ふむ。2番目の文はややこしいなぁ。 SequenceMatcher has expected-case behaviorで、behavior depend on how many elements the sequences have in commonなんですよね。 データに依存しているということはわかるけど、日本語にはどう訳せばわかりやすいのかな…。

計算量: 基本的な Ratcliff-Obershelp アルゴリズムは、最悪の場合はデータ量の3乗のオーダーの時間がかかりますが、通常は2乗のオーダーになると予想されています。 SequenceMatcher は最悪の場合に2乗のオーダーの時間がかかり、 通常の挙動は与えられた配列の中のどれだけの要素が共通であるかによって複雑に変化します。最良の場合の計算量は線形です。

僕はやりたいときにやりたいだけを訳しているだけので気が楽だけど、こんな文章を訳さないといけないとは翻訳チームの人も大変ですね。


__ difflib.Differ().compare(a, b)で簡単に文字列の比較ができますね。

2006年07月26日

Pythonでアッカーマン関数

アッカーマン関数を素直に再帰で書いてみました。

>>> def ack(m, n, indent = 0):
	print "  " * indent + "ack(%d, %d)を計算…" % (m, n)
	if m == 0:
		result = n + 1
	elif n == 0:
		result = ack(m - 1, 1, indent + 1)
	else:
		result = ack(m - 1, ack(m, n - 1, indent + 1), indent + 1)
	print "  " * indent + "ack(%d, %d)は%d。" % (m, n, result)
	return result

>>> ack(2, 2)
ack(2, 2)を計算…
  ack(2, 1)を計算…
    ack(2, 0)を計算…
      ack(1, 1)を計算…
        ack(1, 0)を計算…
          ack(0, 1)を計算…
          ack(0, 1)は2。
        ack(1, 0)は2。
        ack(0, 2)を計算…
        ack(0, 2)は3。
      ack(1, 1)は3。
    ack(2, 0)は3。
    ack(1, 3)を計算…
      ack(1, 2)を計算…
        ack(1, 1)を計算…
          ack(1, 0)を計算…
            ack(0, 1)を計算…
            ack(0, 1)は2。
          ack(1, 0)は2。
          ack(0, 2)を計算…
          ack(0, 2)は3。
        ack(1, 1)は3。
        ack(0, 3)を計算…
        ack(0, 3)は4。
      ack(1, 2)は4。
      ack(0, 4)を計算…
      ack(0, 4)は5。
    ack(1, 3)は5。
  ack(2, 1)は5。
  ack(1, 5)を計算…
    ack(1, 4)を計算…
      ack(1, 3)を計算…
        ack(1, 2)を計算…
          ack(1, 1)を計算…
            ack(1, 0)を計算…
              ack(0, 1)を計算…
              ack(0, 1)は2。
            ack(1, 0)は2。
            ack(0, 2)を計算…
            ack(0, 2)は3。
          ack(1, 1)は3。
          ack(0, 3)を計算…
          ack(0, 3)は4。
        ack(1, 2)は4。
        ack(0, 4)を計算…
        ack(0, 4)は5。
      ack(1, 3)は5。
      ack(0, 5)を計算…
      ack(0, 5)は6。
    ack(1, 4)は6。
    ack(0, 6)を計算…
    ack(0, 6)は7。
  ack(1, 5)は7。
ack(2, 2)は7。
7

うひゃあ。たかが(2, 2)でこんなことになるのか…。すさまじいなぁ。


__

横軸m、縦軸nで原点を左上隅にして値を表示してみました。

      2   3   5  13
  2   3   5  13    
  3   4   7  29    
  4   5   9  61    
  5   6  11 125    
  6   7  13 253    
>>> 61 - 29
32
>>> 125 - 61
64
>>> 253 - 125
128

つまりack(m, n)は

	if m == 0:
		result = n + 1
	if m == 1:
		result = n + 2
	if m == 2:
		result = 3 + n * 2
	if m == 3:
		result = 8 * (2 ** n) - 3

ということみたいです。なおack(4, 0)は13で、ack(4, 1)は65533(これは2 ** 16 - 3)、ack(4, 2)は

>>> from math import log
>>> log(ack(4, 2))
45426.093625176574
>>> log(ack(4, 2) + 3) / log(2)
65536.0

というものすごく大きな数です。2万桁弱。アッカーマン関数がとんでもない関数だということがよくわかりました。


__ m = 0 の時 (n + 1)、m = 1 の時 (n + 1) + 1、m = 2 の時 (n + 1) * 2 + 1、と整理すると m = 3 の時 4 * (2 ** (n + 1) - 1) + 1 になって美しくない。 整理の仕方を間違えていたようです。まず記号を定義しないといけなさそうです。2 * n は 2 を n回足したもの、つまり + という演算をn回繰り返したものです。これを 2 +*n と書くことにします。次に、2 ** n は2をn回掛け合わせた物です。つまり+*という演算をn回繰り返したものなので、2 +**nと書くことにします。最後に、+**という演算をn回繰り返すことは+***nと書くことにします。そうするとアッカーマン関数は

m = 1のとき (2 +(n + 3)) - 3
m = 2のとき (2 +*(n + 3)) - 3
m = 3のとき (2 +**(n + 3)) - 3
m = 4のとき (2 +***(n + 3)) - 3

になる、と書けます。美しい。なお誤解を避けるために書いておきますと、数字の並びから推測してこうなりそうだと言っているだけで証明はしていません。


__ あれ?違う?

ああ、そうか、単に「n回繰り返す」と言っちゃダメなんですね。掛け算までは対称だからそれでも問題は起きないのだけども、累乗は対称ではないので(2 ** (2 ** (2 ** 2)))と(((2 ** 2) ** 2) ** 2)が一致しないわけです。正しいのは前者。

日記

体調悪いと思ったら昨日晩ご飯を食べるのを忘れていました。

Perlはやっぱもう駄目か(enbug diary(2006-07-22))。 を見て、言語間の優位関係はブール束だ、と思ったのですがリンクすべき解説を探して「ブール束」や「boole lattice」で検索しても見つからない。あれれ?と思ったらブール束は英語で「boolean lattice」でした。Boolean algebra - Wikipedia, the free encyclopedia。結局Wikipedia。{Ruby, Perl} > {Ruby}で{Ruby, Perl} > {Perl}だけども、Ruby と Perl の間に順序関係は定義できない、というもの。

うかうかしていられない、7月31日には大阪にいないといけないのだから冷蔵庫の中の物とかなんとかしなきゃ。

YouTube - ラーメンズ 「不思議の国の日本」 1 / 3 (前編)。僕はこれを見てラーメンズにはまったのです。公演の物なので、テレビ番組みたいにカメラワークが悪くて残念なことになったりしていないです。「この謎はおよそ14分後に解けます」とか時間の限られた番組では無理なので消される前にぜひご覧ください。

日経ソフトウェアで増田さんのPython連載が始まるんですね。

右手首がちょっと痛い…。うむむ。

昨日する予定だったデモをFLASHにしてみたのだけども、サイズが大きくて微妙です。全部続けて録画するんじゃなくて、もっと細切れにした方が良かったのかもしれません。

「ミサイルに核弾頭をつけないと費用の割に効果が少ないから、核弾頭の開発が済むまでは打ってこない」なんて言っている人はかつてこの国が何をしたのか忘れたんでしょうか。「人間1人+飛行機」を軍艦にぶつけても費用に見合う効果は得られなかったと思うけど。

サクセス頭皮スッキリ洗浄ブラシは単体で売っているなら買ってみようかと思います。値段次第ですけど。

最近、しゃべろうとして口を動かしているのに声帯のあたりで詰まってしまって声が出ないことが時々。この前ジュンク堂に行ったときに、声を出して読む本を買って、それを読んでみようとして思った通りの声がなかなか出せないことに改めて気づきました。うーむ。

31日から大阪で例のボランティアなので、29日に大阪に帰るとしますかね。服はさっき洗濯して干したし、後は冷蔵庫の野菜とソーセージを食べてしまえばOKかな。

Blog/2006-7-23 - Rocco の日記のコメントに書かれていた「アッカーマン関数を再帰を使わずに書く」というお題に挑戦したくなってしまったのですが「キミならどう書く 2.0」のネタにどうですか(ぇ) どこかで「ブログなんだからお題も募集すればいいのに」という意見を読んだような気がしますけど、中の人にもそれなりに予定があるでしょうから3.0あたりでそういうシステムに変えてみるとかどうでしょう(笑)

西尾泰和のブログ: Pythonでアッカーマン関数。アッカーマン関数がとんでもない関数だと言うことがよくわかりました。ack(4, 2)が2 ** 2 ** 2 ** 2 ** 2 - 3ですから…。mが5以上のことなんて考えたくもないですね。

で、結局また数学になっちゃったので「キミならどう書く 2.0」のネタにどうかという話はなかったことにしましょう。

No Free Lunch Theorem---理想の**の探し方---

AdaBoostを実装してみました。想像以上に簡単でした。

もう26時。照明を買おうかなぁ。明るさのなだらかに調節できるのを。作り付けの照明は夜に明るすぎて眠るモードになりにくい。

2006年07月25日

グラフ可視化ソフトGRINEditを使ったCollatz角谷問題の可視化その2

Blog/2006-7-17 - Rocco の日記。前回のGRINEditで可視化したFLASH(これ)は一気に全部を実行していたので、慣れない人にはわかりにくかったようです。そこでステップ実行のバージョンを作ってみました。PythonとXML-RPCとグラフ可視化ソフトGRINEditを使ったCollatz角谷問題の可視化

こうやって「うねうねつながったもの」がリアルワールドにあったとして、「頂点1から一番離れている頂点はどれ?」と聞かれたなら、1を持ってぶら下げて一番下にたれ下がるのがどれか見てみたくなりますよね。でも、無重力だとたれ下がってくれません。そこで重力を追加したわけです。

こうやって可視化することに意味があるのか、と問われるなら「ない」と答えるでしょうねぇ…。あえて言うなら「面白いから」でしょうか。まぁ、「キミならどう書く 2.0」の参加者は、面白いから解いているんであって、意味があるから解いているわけではないと思います。賛否両論あるみたいですけど、お祭りは楽しんだ方がいいのではないかと。

なおときどきの雑記帖 リターンズの「ソートのアルゴリズムの違いによる挙動の差とか、 木構造の構築、とくにAVL-treeとかの回転(rotate)なんかはこういう風に視覚化できると わかりやすいんじゃなかろうか? 」とのご指摘はもっともです。 それを目指してNarVisualizerを作り、去年の夏のプログラミングシンポジウムで発表したのですが、これ自体よりもこれの整形エンジンの方が需要が高そうだったのでこっちは塩漬けにしてGRINEditをやっています。将来的にはGRINEditの応用例としてNarVisualizerを吸収併合する予定です。

# -*- coding: cp932 -*-
import xmlrpclib
server = xmlrpclib.Server("http://localhost:8080/RPC2")
g = server.grinedit

g.initGraph()

existVertex = {
    1: g.addVertex("BoxVertex",
                   {"label": "1", "anchored": (0.0, 0.0)})
}

def addVertex(x):
    if not(x in existVertex):
        name = g.addVertex("BoxVertex", {"label": str(x)})
        existVertex[x] = name

    return existVertex[x]

def collatz(x):
    raw_input("...")
    # 次の数を求める
    if x % 2:
        y = x * 3 + 1
    else:
        y = x / 2

    print x, "の次は", y, "です"
    toReturn = y in existVertex
    v1 = addVertex(x)
    v2 = addVertex(y)
    g.addEdge("LinearEdge", {"v1": v1, "v2": v2, "directed": True})

    if toReturn:
        print y, "はすでに計算済みなので計算を中断します"
        return
    collatz(y)
        
for i in range(2, 11):
    if i in existVertex:
        print i, "はすでに計算済みなのでスキップします"
        continue
    print i, "についての計算を始めます"
    collatz(i)
    raw_input("...")

#g.addLaw("PL_Gravity", {})

日記

情報処理学会が学生会員という扱いになっていたのを正会員に変更、そうすると会費の請求額とは違う額を納めないといけないのでややこしいけど、ちゃんと計算したのでたぶんあっているはず。今まで学生会員4800円+研究会1個無料だったのが、正会員9600円+研究会(数理モデル化と応用)3885円で13485円。割と高いなと思ったけども、年間でこれくらいだったらそれほど高くもないのかな…。とりあえず今から振り込んできます。

振り込んで帰ってきたら先生が倒れて救急車で運ばれるところだったのでびっくり。

無事帰ってこられて一安心。

2006年07月24日

rpc用インターフェイス

現在、例えばlabelというフィールドを書き換えるメソッドはvoid rpc_label(Object)なのですけど、これはvoid setLabel(Object)にしてしまっても大丈夫な気がしてきました。XML-RPCで呼ぶときは"label"という文字列からリフレクションでrpc_labelメソッドを取得しているので、引数がObject型なのは変えられないのですが、メソッドの名前は別に今の物にこだわる必要はないわけです。で、Jythonインタプリタから操作する場合に、いちいちRPC用のと別にメソッドを用意しておくのは面倒です。そこでRPC用のメソッドを呼びたいわけですが、こちらは名前が裸で出るのでv.rpc_label("newLabel")なんて書くことになります。かっこわるいです。一方、v.setLabel("newLabel")ならごく自然です。

そもそも最初にsetLabelを使わなかったのは、JavaやPythonから呼び出す場合に引数がObjectでないといけないのはウザイかな、と思ったせいなのですが、上記の通りJythonからの呼び出しのために別口を作るのは面倒ですし、JavaやJythonからの呼び出しは同名でも別のシグネチャなら問題なく呼び出せますから、そもそもの心配が杞憂だったということになります。

むむ、メソッド名をsetBackgroundColorにするとXML-RPCの時に"BackgroundColor"をキーにするか、1文字目を大文字に変換する作業かどちらかになるか…。

大文字に変換するのの方が見栄えはよさそう。

GRINEditのデモ:Jythonコンソール。眺めるためのデモと読ませるためのチュートリアルの両方を作るべきなのかもしれない。これはソースコードを追おうとすると早すぎる。1ページに収まっているので、止まった後でじっくり読むことはできるけども。チュートリアルはNEXTボタンをぽちぽちクリックして自分のペースで読める方がいいし、デモはちまちまクリックさせられずにぼーっと眺められる方がいいのだろうと思う。

「キミならどう書く 2.0 Round2」は難しいのか、つまらないのか

キミならどう書く 2.0 - ROUND 2 の問題文がもしこう書かれていたら、世間の評判はどう変わったでしょうか。

ある1以上の整数 n に、

  • n が1なら停止する。
  • n が偶数の時は、nを2で割る。(n = n / 2)
  • n が1以外の奇数の時は、nを3倍して1を足す。(n = n * 3 + 1)

という手続き f を繰り返し適用することを考えます。どんな整数 n からスタートしても、繰り返し f を適用すると、かならずいつかは n が 1 になり停止するのではないかと思われています。(コラッツの問題 - Wikipedia)

例えば3からスタートすると、

3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1 -> 停止

と、 手続き f を8回実行して停止します。これをステップ数と呼ぶことにします。 さて、「100までの整数で、停止するまでのステップ数が最も大きい数」はなんでしょうか?

「簡単すぎてつまらない」という人が増えたでしょうか。これを見て「なんだ、あの難しそうな問題文はそういう意味だったのか」と思う人も多いのでしょうか。

今回の問題は、問題文に使われている言語こそ難しかったですが、技術的に難しいところはありませんでした。問題が簡単すぎるという意味での「つまらない」という意見には、そういう意味では賛同します。この問題をゴールだと考えると簡単すぎてつまらないでしょうね。 でも、だからこそ一部のチャレンジングな人は、例えば「ものすごく大きい数についての計算に挑戦する」や「少ない文字数でコードを書くことに挑戦する」などの課題を自分で作り出してそれに挑戦していたのではないでしょうか。(僕の場合は「Schemeでdefineを使わずに書く」と「物理法則を使って可視化してみる」でした。)

お祭りは盛り上がらないと面白くないですから、難しすぎて挑戦者が少なすぎるよりは、簡単すぎる方がマシかと思います。簡単な問題なら、参加者が自分でもっと難しくすることができますから。でも今回の問題は、内容自体は簡単だったのに、問題文が難しすぎたようですね。例えば2文目の「Collatz予想とは,1以上の自然数 n に対して,次の関数 f(n) が必ず1を返すものとする.」も、関数fが再帰的な定義になっていて、慣れていない人にはわかりにくいですよね。hの定義も数学語で書かれていて読みづらいですよね。そういう難解な問題文を苦労して読解したら実はお題はすごく簡単だった、となるとガックリくる人も多いのかも知れませんね。

三すくみに関する考察

渡辺さんの日記に反応。

相対評価関数が「勝率」を使って定義され、値域が「-1 < f(a,b) < 1」になっているところから、エージェントの行動が非決定的だという仮定を置いているように思えます。三すくみを考察するときに、決定的なエージェントの方が考えやすいのか、非決定的なエージェントの方が考えやすいのかは僕にはわかりません。決定的な方がシンプルで考えやすい気もしますが、非決定的な方が偏微分したりできて面白い気もします。

とりあえず値域を-1 <= f(a,b) <= 1にしてみます。すると、f(a, b) = a[0]b[1] + a[1]b[2] + a[2]b[0] - a[1]b[0] - a[2]b[1] - a[0]b[2] という相対評価関数で 戦略ベクトルが(1, 0, 0), (0, 1, 0), (0, 0, 1)のどれかに制限されているエージェントを戦わせると、いわゆる「じゃんけん」になるわけですよね。

ところで、多数のエージェントがリーグ戦をする場合、相対評価関数は1対1のf(a, b)に限らなくても、f(x_i, x_0, ..., x_n)でいいような気がします。関数の値を勝率から定義してあると値の範囲に色々制限がつきますが、関数の値が単なるスコアなら何の気兼ねもなく全部足しあわせてしまって構わないですね。そうすると、x_0, ..., x_nを面倒なのでΦと書くことにすれば、エージェントiの学習はf(x_i, Φ)が大きくなるようにx_iを変えることですね。で、すべてのエージェントが同じタイミングで学習をする(「何もしない」という学習の仕方も含めて)なら、結局学習のステップというのは何か一つの関数Fを使ってΦnew = F(Φ)と書けることになります。このFがストレンジアトラクターを持っていたりするとエージェントを学習させている側としてはかなり嫌な感じですね。

と、話をふくらませただけで何の解決もせずにネットの海に投げ込んでみます。富栄養化(笑)

そうそう、じゃんけんみたいなわかりやすい三すくみではないけども、実際にプレイすると「すくんでいる」ような関係を設計する技術は、もしかしたらゲーム作りに役に立つのかも知れませんね。少なくとも、 名刺をトレーディングカードゲームにする話では、ある人の名刺がすごく強くて他の人を倒しまくってしまったりするとよろしくないので、うまい具合にすくませる必要がありますよね。プログラマはコンピュータに強く、普通の人はコンピュータに弱く、プログラマは普通の人に弱い。しまった、コンピュータは名刺を持っていないからプログラマが一方的に負けてしまう!(汗)

日記

ふぅ、電源があるとほっと一安心。

先日の「一単位の英語の勉強をするたびに1つの印をつけていく」という方法は行動分析学の言葉ではパフォーマンスフィードバックと言うようです。あと部屋全部を掃除するのは何度も挑戦して失敗しているので、確実に実行できるように「廊下を掃除する」という目標に変えた行動は神経言語プログラミングの言葉ではチャンキングと言うようです。

ちなみに昨日で生まれてから四半世紀が過ぎました。とか思っていたら親から電話がかかってきて「四半世紀過ぎたね」と言われました。思考回路一緒なんだなぁ…。

あと「四捨五入すると三十路」ってのもきっと誰かに言われるので先に書いておきます(笑)

ぎゃー。 小さい方のLinkStationの内容を大きい方のLinkStationに移動しよう…と週末ラボに放置しておいたのですが、今日になって中を見てみると何かおかしい…。何がおかしいのかというと、大きいLinkStationを買ったつもりが、一世代古い(HGじゃない)LinkStationを買っていて、今のLinkStationと同じ大きさでした!わー。どうしよう、これ…。

とりあえず移動したファイルをまた元に戻そう。古いLinkStationでもLinux化はできるようなので、CVS/SVNサーバにでもしようかなぁ…。

Macはやっぱりまだ慣れていないのでなかなかです。Deleteキーを押してもファイルが消えてくれないなぁ、とか、WindowsならAlt+F Rでプロパティが見られたのに、Macではいちいち画面を見てクリックしないといけないのかなぁ、とか。どこかを見ればキーアサインが書いてあるのかも知れないけど、メニュー自体に書いておいてくれれば楽に習得できるのになぁ、と思うわけです。まぁそれ以前にMacのキーボードではないのでほとんどのキーアサインが使い物にならないのですが。キーボードのマッピングを変えるソフトを探さなきゃねぇ。

とりあえず後輩に送ってもらった古いサーバのZopeのExtensionとProductsをコピーして以前のサイトをローカルで復元しました。これから時間のあるときにちまちまと以前のコンテンツを移植することにします。続きはまた今度。

明日GRINEditをラボ内でプレゼンするので久しぶりにJythonからグラフを操作しています。

MacでGRINEditを動かしてみたらUnsupportedClassVersionErrorが出ました。ふむ…これはJDK5.0を入れればいいのかな?いや、なんか入ってそうだ…でもどこにあるのかわからない…。

Apple - Support - Downloads - Java 2 SE 5.0 Release 1で見つけてインストールしようとしたら「このボリュームにはもっと新しいJavaが入っているからインストールできないよ」と言われました。やっぱりどこかに入っているそうです。

新しく来た「古いLinkStation」はファームウェアが3.01と最新のためtelnetで接続することすらできませんでした。Linux化するどころじゃない、と。したかったらHDDを取り出して別のマシンでマウントしないといけなさそう。うーん。そして古いバージョンだからUSB端子もないし、古いバージョンだから1000baseでもない。何に使おう、これ…。

GRINEditのデモ:Jythonコンソール。あ、最近FirefoxでFLASHが表示されなくて困っていたけど、ローカルのHTMLからリンクされているFLASHは問題なく表示されるので不審に思って調べていたらAdblockの設定でObjectタグが禁止されているのが原因かもという情報が。きっとそれですね。再起動してきます。

うかうかしていたら11時を過ぎていつもの路線で帰れなくなったので新橋→秋葉原経由で帰ってきました。

もう26時。最近、2袋目の無洗米がなくなったので買いに行ったところ、レイアウトが変わっていて無洗米が見つからなくなっていたので「金の芽ーがあーるきんめまーい」を買ってきました。これも無洗米らしいので。でも5キロ。今までお米は冷蔵庫の野菜室に入れていたのですが(狭くて野菜の入らない野菜室なので)5キロの袋はさすがに入りません。常温で置いておいて大丈夫なのかな。虫がわくのかな。無洗米でも?

とりあえず寝ます。

2006年07月23日

日記

ジュンク堂で久しぶりに本をたくさん読んだので疲れました。

Haskellが楽しそうでした。

あとなぜか眼がかゆいです。くしゃみも出ます。花粉?

例えば「毎日○○する」という目標だと1日成功してもあまり目標に近づいた感じがしないのに、1日失敗すると目標の達成が不可能になり一気にやる気が失せてしまいます。「気が向いたら○○する」で成功した日を記録していく方式なら、成功して記録用紙に記録するときに達成感を感じられるかも知れません。「これで10日目だ!」とか「3日連続だ!」という達成感も感じられ、後付で「次は20日を目指そう」とか「10日連続を目指そう」という目標ができあがるかも知れません。ただ、この方法は記録用紙自体をなくしてしまうと無力ですよね…難しい。あ、なくならないようにブログに書くのか、それはいいかも。

ゲド戦記は3巻まで読んだけども、CMの「命を大切にしないやつはだいっきらいだ!」の女の子は誰なのかさっぱりわかりません。オリジナルキャラですかね。それとも4巻に出てくるんですかね。

バッテリーが残り6パーセント。

2006年07月22日

日記

椅子届きました。これで背中にパイプが食い込むこともないでしょう。

片付けがなかなかできないのは、片付いた達成感を感じる経験が少ないからでは。というわけで、今日中に達成できそうな規模にタスクをブレイクダウンして片付けることにしました。「廊下を片付ける」と。お茶の箱が壁と癒着していたり、空だと思っていたコンビニ袋に使用済みのお茶のパックが入っていて汁が垂れていたり、いろいろハプニングはありましたが、きれいになりました。何にもなし。床の上とかに出しっぱなしだった食器を棚の中に詰め込んだので次はアレを片付けないといけませんが…、そういうことは考えずにとりあえず「廊下は片付いた!」と喜ぶべきなのでしょうかね。

バッテリーが少なくなってきてだんだん心細くなってきました。

どうしてGTDできないか、を考察してみたり。結局のところ、多種多様なタスク管理の手法があるにもかかわらずどれもうまく行かないというのは、「直すべき所」を間違えているからなのではないかと思いました。たとえばタスクを時間で区切って締め切りを設けることで集中力を上げようという戦略で「2時間に区切れ」という案や「2時間ではなく20分×6に区切れ」という案があったりするわけですけど、どちらが正しいのかはタスクの内容によって異なるわけだから本質的ではないわけです。で、2時間を試してみてダメで、20分を試してみてダメで…という試行錯誤の結果、正しい区切り方にたどり着く人もいるだろうけども、たどり着かない人もいるわけです。たどり着かない人は、まだ正しい区切り方に出会っていないのではなく、そもそも問題点が別の所にある可能性があります。習慣化能力とか。僕の場合は何か方針を定めても適切なタイミングでそれを思い出す能力が低いわけです。お風呂に入る前にタオルがあるか確認する、と決めても実際に入るときにそれを思い出せないので結局週に何回かはタオルがなくて濡れたままタオルを取りに出てこないといけないわけです。そういう「習慣化能力の低さ」を自覚して、習慣を定着させるにはどうしたらいいかを考えないといけないと思います。うーん。「習慣を定着させるためにこれをする」という習慣を作る方法では方向性としてダメですよね。


__ 習慣化に成功していることと、習慣化に失敗したことは何が違うのかを検討。

明日はジュンク堂や東急ハンズに行ってじっくり物色することにしようかと思います。

精神的な弱さの改善を精神論に頼るのはおかしいので、例えば自己暗示や教科学習(オペラント条件づけって言うのかな?)、薬物などの科学的な手法に頼るべきなのだと思う。

Installing a new habit and breaking an old oneNBonline(日経ビジネス オンライン):Lifehacks コラム・トップ。読み始めると途中でバッテリーがなくなりそうで。

バッテリー残り14%で明日1日を過ごさなければならない…。温存するか…。

2006年07月21日

日記

うー。今やっと、昨日走らせたジョブが終わった。

椅子を発送したそうなので明日か明後日には届くことでしょう。

楽天クレジットカードが未だに届かないのはなぜ。

クラスタ化インデックスを使うとソートされた状態で取り出せるらしい。


__ ラボのリフォーム。 Mac miniにZopeを入れ、古いサイトをエクスポートしておいた物をインポート。しかし、古いサーバの中のProductsとExtentionsがないとサイトは復元できないことに気がつく。

今日の行きの電車でゲド戦記3を読了。楽天ブックスで「エヌ氏の遊園地」(星新一)を購入。

「楽天ブックスの便利さ」ではなくて「『安い本でも送料無料』の便利さ」なのだけど、 1冊の文庫本を読もうと思ったその時に十数クリックすれば、数日後家のポストにそれが入っている、というのはとても便利。今まででも送料を気にしなければ同じ便利さを享受できたはずだけども、無産階級の悲しさで節約してしまう。


__ はてなでつまらないことを質問してしまった…。


__ この文章はMac miniから書いています。とりあえずCtrl+Shift+J で日本語モードになってCtrl+Shift+;で英語モードになるということは覚えました。本当はひらがなキーや英数キーでも切り替えられるんですけど、今つないでいるキーボードが英字配列なので、、、正確に言うとちょっと特殊で、左シフトキーの隣にあるキーには「Zㄈ重心」と書いてあるんですけどね。ㄋㄧ3で你が出るのだけど好を出そうとしてㄏㄚㄛと打ってもㄏㄛになってしまう。謎。あとコピペをしようとしてCtrl+C,Vを押したら期待と違う挙動をしたり。なかなかいいパズルです。

注音符号 - Wikipediaの図を見て、aoがないのでaとoを組み合わせてㄏㄚㄛにしたのだけど、正解はauと書いてあるㄠを使ってㄏㄠとするんだそうです。このページの下の方の説明を読むと確かにそう書いてありますね。あと注音符號 - Wikipediaを見るとおのおのの文字の由来が書いてあっていいですね。ㄒは下(xia)が元になっているから発音がXなんですね。ㄠはヤオチューハイのヤオですね(麻雀かよ!)


__ パソコンの電源を忘れたかも。というか探しても見つからないからたぶん忘れたんだろう。あーあ。


__ TAKESAKO @ Yet another Cybozu Labs: AJAJA - Yet Another Server Side JavaScript。 サーバサイドJavaScriptは久しぶりに目から鱗が落ちました。確かにサーバサイドをJavaやPHPでやって、間をXMLで通信して、クライアントサイドをJavaScriptでやるのはキメラみたいで変ですよね。サーバでJavaScriptが動いて、間の通信をJSONにすると、とてもすっきりしそう…。

とりあえずPPTをダウンロードして呼んでみたけども、僕にできることはなさそうです。僕もあまり浮気をしないでGRINEditを仕上げることに注力するべきかも知れません。今週は全然いじる時間を取れてないですけど。

とりあえず次の月曜にラボのMac miniにApacheとAJAJAを入れてみよう。


__ バッテリーが残り57%…。うーん。このバッテリーで土日を過ごすのは寂しいなぁ。