過去の日記

2012-11-01

10月の読書メーター

読んだ本の数:12冊
読んだページ数:3381ページ
ナイス数:12ナイス

OUT OF CONTROL (ハヤカワ文庫JA)OUT OF CONTROL (ハヤカワ文庫JA)感想
「まあこ」と「箱」は異形コレクションで既読。「箱」は題名だけでストーリーラインを思い出せる程度に印象が残っていた。やっぱり面白い。「まあこ」は取り出して読むと面白いのだけど、異形コレクションの中では……。そういや全体的に今ひとつの巻だったかも。「メトセラとプラスチックと太陽の臓器」が面白い。「OUT OF CONTROL」はすごくよくできていて、何度も読める作品なんじゃないかという予感。「スタンド・アウト」は興味深い。「デストピア」は半端。「日本改暦事情」は今となっては"天地明察を読め!"という気分。
読了日:10月31日 著者:冲方 丁

2000年のゲーム・キッズ(上) (星海社文庫)2000年のゲーム・キッズ(上) (星海社文庫)
読了日:10月22日 著者:渡辺 浩弐,竹

暗黒太陽の浮気娘 (ミステリアス・プレス文庫―ハヤカワ文庫 (10))暗黒太陽の浮気娘 (ミステリアス・プレス文庫―ハヤカワ文庫 (10))感想
話の筋として知ってはいたけど、D&Dのプレイングの最中に犯人をあぶりだすミステリって……変。SFファン(作中表現を尊重してオタクとは書かない)の生態が楽しい。今は有名な《プラン9・フロム・アウタースペース》が《外宇宙からの第九次侵略計画》として名前だけ登場。ここのやりとり「あら、見なきゃだめよ! 信じられないくらいひどいんだから」は可笑しい。(《マウス・オブ・マッドネス》でモーテルのテレビに映っていた)《ロボット・モンスター》は《怪物ロボット》だったり。D&Dのプレイ中に出てきた変化(へんげ)ってなに?
読了日:10月19日 著者:シャーリン・マクラム

カンナ 京都の霊前 (講談社ノベルス)カンナ 京都の霊前 (講談社ノベルス)感想
あっさりとした解決。QEDの、日本史の話をしていたと思ったらミステリの謎に繋がってました、というフォーマットに縛られていない分こちらの方が好き。日本史の話で盛り上がってお仕舞いでokなので。
読了日:10月15日 著者:高田 崇史

カンナ 出雲の顕在 (講談社ノベルス)カンナ 出雲の顕在 (講談社ノベルス)
読了日:10月15日 著者:高田 崇史

カンナ 天満の葬列 (講談社ノベルス)カンナ 天満の葬列 (講談社ノベルス)感想
道真公の生前が悪霊のイメージからはほど遠いというのは永井路子の悪霊列伝などでも既知。悪霊列伝では寺社の権力(?)争いに求めていたかなー。こちらの解釈の方が面白い。
読了日:10月15日 著者:高田 崇史

カンナ 鎌倉の血陣 (講談社ノベルス)カンナ 鎌倉の血陣 (講談社ノベルス)
読了日:10月14日 著者:高田 崇史

カンナ 戸隠の殺皆 (講談社ノベルス)カンナ 戸隠の殺皆 (講談社ノベルス)
読了日:10月14日 著者:高田 崇史

カンナ 奥州の覇者 (講談社ノベルス)カンナ 奥州の覇者 (講談社ノベルス)
読了日:10月12日 著者:高田 崇史

カンナ 吉野の暗闘 (講談社ノベルス)カンナ 吉野の暗闘 (講談社ノベルス)
読了日:10月10日 著者:高田 崇史

クトゥルフ神話への招待 ~遊星からの物体X (扶桑社ミステリー)クトゥルフ神話への招待 ~遊星からの物体X (扶桑社ミステリー)
読了日:10月9日 著者:J・W・キャンベルJr.,H・P・ラヴクラフト,ラムジー・キャンベル

復興の書店復興の書店感想
もう震災関連の書籍は読まなくても、と思っていたがこんなものを見つけた日には手に取らずにいられない。p40「生活に必要な食料や水を買い求めるためにスーパーに並んだ人たちが、同じようにその足で書店にも並んでいるんですよ」本屋の開店も、新刊の配本も、図書館の再開も、みな待ち遠しかった。本屋さんは私にとっての日常の象徴だった。この本を読んで、あらためてそう思う。一頁堂書店さんが、みんな全くの素人というのは意外だった。巻頭の地図が位置がよく把握できるのでよかった。
読了日:10月8日 著者:稲泉 連


2012-11-07

SonyMusicのアーティストの取り扱い開始 [iTS]

と聞いて、さっそく探してみる。

ルミナス - EP - Claris

ひかりふる - EP - Kalafina

あったあった。
つい数日前に買おうか考えてやめたのだった。

……探してしまう自分がなんだかなぁ。



2012-11-14

datetime型のタイムゾーン変換 [Python]

の正着はなんだろうか。

とりあえず、naiveなdatetimeインスタンス(UTC相当の時刻)から、awareなdatetimeを持ってくるのに、

> pip install pytz

を使って、

import pytz

utc=pytz.timezone('UTC')
jst=pytz.timezone('Asia/Tokyo')

aware = naive.replace(tzinfo=utc).astimezone(jst)

としてみた。


2012-11-19

Pythonで多次元の辞書を扱う [Python]

nodes[0][9][3]=3
nodes[0][9][4]=5

みたいな感じに使いたい*1
今、添え字は数字にしてあるけど、実際はこの部分は辞書*2のキーの扱いにしたくて、つまりは文字列とかもつっこみたい。
検索すると、辞書のキーにはタプルが使えるので、

nodes[(0, 9, 3)]=2
nodes[(0, 9, 4)]=3

みたいに書けますよ、というのはでてくるけど、

for i in nodes[(0,9)]:
    print i #=>3(改行)4(改行) とでてほしい

みたいな書き方はできない。
これは今回の目的にはそぐわない。


ちょっと横道にそれるけど、実はdefaultdicみたいな書き方もしたかったりする。

print nodes[0][9][8] #=>0 とか。これをKeyErrorにしたくない

という感じ。

from pprint import pprint
from collections import defaultdict

nodes=defaultdict(int)
nodes[0] = 5
nodes[2] = 10
pprint(nodes) #=> defaultdict(<type 'int'>, {0: 5, 2: 10})
pprint(nodes[4]) #=>0
pprint(nodes) #=> defaultdict(<type 'int'>, {0: 5, 2: 10, 4: 0})

となる。
おさらい終わり。


nodes = defaultdict(dict)

と書いてみる。

nodes[0][0]=5
nodes[0][2]=10

ok。2次元配列みたいに代入できる。
nodes[0]に初めてアクセスしたときに空の辞書がセットされるからだ。
でもこれだと、

pprint(nodes[0][4]) #occurs KeyError

うん当然。nodes[0]は普通の辞書なわけだから。

じゃあdefaultdictのデフォルト値がdefaultdictになればいいんじゃない?

nodes = defaultdict(defaultdict(int)) #occurs TypeError: first argument must be callable

defaultdict(int)がcallableじゃないっていわれる。
ふむ。
callableならいいんだね? ならばlambdaだ。

nodes = defaultdict(lambda : defaultdict(int))
nodes[0][0]=5
nodes[0][2]=10
pprint(nodes[0][4]) #=>0

いいかんじ。


次は3次元。

nodes = defaultdict(lambda : defaultdict(lambda : defaultdict(int)))
nodes[0][1][0]=5
nodes[0][1][2]=10
pprint(nodes[0][1][4]) #=>0


ふむ……。なるほど。

nodes = defaultdict(lambda : defaultdict(lambda : defaultdict(int)))
                                         ^^^^^^^^^^^^^^^^^^^^^^^^^

ここの部分が、一段上のdefaultdicに与えてやった初期値に等くなる。
defaultdic.default_factoryで引っ張ってこれそう。

def multi_dimension_dict(dimension):
    nodes = defaultdict(int)
    for i in range(dimension-1):
        lm = nodes.default_factory
        nodes = defaultdict(lambda : defaultdict(lm))
    return nodes
nodes = multi_dimension_dict(2)
nodes[0][0]=5
nodes[0][2]=10
pprint(nodes[0]) #=>defaultdict(<type 'int'>, {0: 5, 2: 10})
pprint(nodes[0][4]) #=> 0
pprint(nodes[0]) #=>defaultdict(<type 'int'>, {0: 5, 2: 10, 4: 0})
nodes = multi_dimension_dict(3)
nodes[0][9][5]=3
pprint(nodes[0][9][5]) #=> 3
pprint(nodes[0][9]) #=>defaultdict(<function <lambda> at 0x108067938>, {5: 3})
pprint(nodes[0]) #=>defaultdict(<function <lambda> at 0x103d7a938>, {9: defaultdict(<function <lambda> at 0x103d7a938>, {5: 3})})

よしよし。

nodes = multi_dimension_dict(3)
nodes['aa']['bb']['cc']=4
nodes['aa']['bb']['dd']=3
pprint(nodes['aa']['bb']) #=>defaultdict(<function <lambda> at 0x109a51b18>, {'cc': 4, 'dd': 3})
sum=0
for key3rd in nodes['aa']['bb']:
    sum += nodes['aa']['bb'][key3rd]
pprint(sum) #=>7

nodes['dd']['aa']['cc']=8
nodes['dd']['bb']['dd']=6
sum=0
for i,n in nodes.iteritems():
    for j,o in n.iteritems():
        for k,p in o.iteritems():
            sum += nodes[i][j][k] #sum += p と等価
pprint(sum) #=>21(4+3+8+6)

まあいいんじゃないですか?

でもこれだとintしか入れられない。

def multi_dimension_dict(dimension, callable_obj=int):
    nodes = defaultdict(callable_obj)
    for i in range(dimension-1):
        p = nodes.copy()
        nodes = defaultdict(lambda : defaultdict(p.default_factory))
    return nodes

にしたらいいかも!!


問題は、

nodes = multi_dimension_dict(3)
nodes[0][1]=3
nodes[0][1][3]=0 #occurs TypeError

とか次元を間違えて代入しちゃうとリカバリが効かないこと。
これは解決方法が見つからないので使う時に注意するしかないかなー。

*1 「多次元の辞書」っていうよりは、「スパース(疎)な多次元配列」といった方が感覚に近い。

*2 Rubyで言うとHash。


2012-11-20

tDiary

レポジトリ*1にマージ漏れがあったみたい。
何がどうなったか追い切れてないけどとりあえず動いている……。

*1 私のプライベートレポジトリのこと。tDiary本体の話じゃない。


2012-11-24

インストールしたモジュールの場所が分からない [Python]

pip install したモジュールがどこに配置されたのか分からなかった。

import hoge
print hoge.__file__

2012-11-26

random.shuffleの話 [Python]

かなり小さい len(x) であっても、 x の順列はほとんどの乱数生成器の周期よりも大きくなるので注意してください; このことは長いシーケンスに対してはほとんどの順列は生成されないことを意味します。

9.6. random - 擬似乱数を生成する - Python 2.7ja1 documentation

どういうことだろう?

例えば乱数の周期が5しかないとする。この乱数で要素5の配列をシャッフルする。
[4, 2, 3, 5, 1]
とでた。
まあシャッフルされたっぽい。
繰り返してみる。
[2, 3, 5, 1, 4]
[5, 1, 4, 2, 3]
[4, 2, 3, 5, 1]
[1, 4, 2, 3, 5]
[5, 1, 4, 2, 3]
という感じで出てきた。
順列組み合わせは5!あるはずだが、[4, 2, 3, 5, 1, 4, 2, 3, 5] の部分列5種類しか出てこない。

こういうことが起きるって話か。


ところで「かなり小さい len(x)」っていったいどのぐらいだろう?

Python は中心となる乱数生成器として Mersenne Twister を使います。これは 53 ビットの浮動小数点を生成し、周期が 2**19937-1、本体は C で実装されていて、高速でスレッドセーフです。

9.6. random - 擬似乱数を生成する - Python 2.7ja1 documentation

周期は2**19937-1だそうだ。
桁数だけ評価する
\(\log_{10}~2^{19937}~+~1=~19937~\times~\log_{10}~2~+~1\) ですな。

import math
19937*math.log10(2)+1=6002.635023552793

まあ、6002桁ぐらい*1

順列組み合わせが6002桁ぐらいになる配列。

math.log10(math.factorial(2081)) #=> 6003.615625445271

このへんか。
2000個程度の配列から上はrandom.shuffle()は十分にランダムではない。
実際は、もっと小さな配列からrandom.shuffle()の結果に周期性が入り込んでくるはずだ。

*1 mathモジュールは19937*math.log10(2)+1でもmath.log10(2**19937)+1でも、同じ結果を返すのだけどね。:-P