脳ざらし紀行


2006-08-10

_ プールの排水口

プール自体の大きさと衛生面の要請から一定時間内にポンプで循環させる水の量は決まってくるだろう。で、循環させる水の量と排水口の大きさを決めたら、排水口に流れ込む水流の速さが決まる。というわけで、事故を防ぐために水流を遅くしたいなら(正確には排水口付近の水流を発生させている圧力を小さくしたいなら)、排水口は大きくしないといけない。あるいは、小さな排水口をたくさん作るとか。


2006-08-11

_ ななつのこ

ホテルで暇だったので、加納朋子『ななつのこ』を買って読んだ。これ前に読んだことあるな。ほとんどストーリーを忘れていたので楽しめたけど。で、続編の『魔法飛行』も買って読んだ。これも前に読んだことがあるような。楽しめたからいいか。

本の画像

_ 本屋での氷室冴子の探し方

普段ライトノベルを読まないけど、名前の通り軽く読めて時間つぶしには最適だろうから読んでみようとふと思った。手始めに、名前を知っている数少ないライトノベル作家のひとりである、氷室冴子の作品を探してみた。けど、なかった。取り敢えず、氷室冴子から読み始めていけば、何時かは『涼宮ハルヒの憂鬱』にたどりつけるだろうと思ったのですが。

_ Adobe Reader 7.0.8 for Linux(rpm)

いつのまにか出ていたのでインストール。


2006-08-12

_ プラモ劇場

ガンプラのコマどりで『涼宮ハルヒの憂鬱』のエンディングを作っていた人が、あの後も色々作りつづけていて、しかも段々と上手くなっている。


2006-08-13

_ UNIX のプロセスに関する問題

入門 OpenSSH』を読んでいたら、

eval `ssh-agent`

ではなくて、

ssh-agent bash

を使え、と書いてあった。そこで、~/.zlogin に

ssh-agent zsh

と書くようにした。こうすると、zsh は ssh-agent のサブプロセスとして実行され、ssh が必要とする SSH_AGENT_PID などの環境変数がサブプロセスへと継承される。はずである。zsh が終了すると、ssh-agent を終了する。

さて上のように ~/.zlogin に書いた状態でログインして pstree を見てみると、

init-+
     |-login---zsh---zsh-+-ssh-agent
                         `-pstree

となっている。おかしい。ssh-agent の子プロセスになっているはずの zsh が逆に親プロセスになっている。にもかかわらず、SSH_AGENT_PID などの環境変数は適切に設定されている。これはどうしてだろう。これが最初の問題。

ssh-agent のソースを読んでみた。答えは簡単で、ssh-agent は子プロセスではなく、親プロセスで execvp を実行しているんですね。子プロセスの方で、ssh-agent の仕事を引き受けている。だから、上のような pstree の表示になる。

では、次の問題。zsh が終了した時に子プロセスである ssh-agent は終了するだろうか。終了しないなら、どのような時に終了しないか。

本の画像

_ ヘッドホンとスピーカーの切替え

ワイヤレスヘッドホンを買おうと思った。だけど、ヘッドホンとスピーカーを切替えるのにコンポのところまで歩いていかないといけないんじゃあんまり便利にならないなあと思い直す。

リモコンひとつで、ヘッドホンとスピーカーを切替えることが出来るような何かって売ってないんですかね。


2006-08-14

_ ゲド戦記

見てきた。割と面白かった。素人の監督が劇場用長編アニメを作ったと聞くと、どうしても『ガラスの艦隊』のような出来を想像してしまうけど、全然そんなことはなかった。原作があってストーリーが単純ということもあるだろうけど、ちゃんと映画として成立していた。単純なストーリーの割に最後まで退屈しなかったのは、脚本も兼任する宮崎吾郎監督の力量なんだと思う。

過去の宮崎駿アニメっぽいシーンが多数出てくるけど、観客はジブリっぽい『ゲド戦記』を見たくてきているわけで、これはこれで良いのでは。劇中の奴隷の描写が宮崎駿の『シュナの旅』そのままだったのはびっくりしたが、クレジットを見ると原案として挙げられていた。

父親を殺してしまったニートな若者が、逃亡中にツンデレな少女と出会って、農作業のよろこびに目覚める話です。

それにしても、全くの素人にちゃんと映画を作らしてしまう宮崎駿の遺伝子はすごいですね。冷凍保存した上で、世界遺産に指定して、後世に残しておくべきなんじゃないかと。


2006-08-15

_ スペース

加納朋子著『スペース』、読了。『ななつのこ』、『魔法飛行』の続編。

ふとした日常の出来事の裏に隠されたちょっとした謎を解いていくのがこのシリーズの醍醐味ですが、この巻では、本当に事件らしい事件が起こりません。それでも〈謎とき〉がちゃんと仕込まれています。事件が起こらないことそれ自身が、この巻においては最大の謎であると言えます。反則ぎりぎりのような気もしますが、面白かったのでOKです。

本の画像


2006-08-16

_ 喫煙者には補助金を出そう

たばこを規制すべきかどうかに関して、社会的費用の観点から。

(人々の危険な行為に対して)規制をしないと、(医療費などの)社会の負担がほんとうに増えるのかどうかは疑問であり、喫煙者の場合はとくにそうである。喫煙者がたばこの害で病気になるとしても、その療養期間は比較的短く(少なくとも肺ガンの場合はそうである)、 社会保障制度から年金をたくさんもらう前に死んでしまうケースが多いからだ。この観点から言えば、通常の経済的分析では、喫煙者に補助金を出してもいいくらいである。

ロバート・バロー著『経済学の正しい使用法』 P194

なるほど。

本の画像


2006-08-17

_ 日本語と n-gram でも Zipf の法則は成り立つか

Zipf の法則というのは以下のようなものです。英語で書かれた長編小説を用意します(小説でなくてもいいんだけど)。そして、本文中に出てくる英単語を頻度順に並べます。すると、第2位の単語の頻度は第1位の単語の頻度の半分になります。第10位の単語の頻度は第1位の単語の頻度の1/10です。第100位の単語の頻度は第1位の単語の頻度の1/100です。そんな感じの法則です。リンク先にもあるように対数グラフにプロットするときれいな直線になります。

さて、Zipf の法則は日本語に対して当てはまるでしょうか。とはいっても、日本語は英語みたいに単語毎に区切ることが簡単ではないので、ここでは n-gram を使います。2文字毎に文を区切って、その2文字を単語だと思って頻度を数えます。ひらがなと漢字だけを対象にしました。日本語のデータとしてはこの日記の本文を使いました。

REG = /([ぁ-ん亜-腕]([ぁ-ん亜-腕]))/e
H = Hash.new(0)

def count(line)
  while REG =~ line
    word = $1
    c = $2
    H[word] += 1
    line = c + (Regexp.last_match.post_match || '')
  end
  return line
end

def read_and_count(io)
  ret = ''
  io.each_line{|l|
    ret += l.chop
    ret = count(ret)
  }
end

def plot2(h)
  h = h.to_a.sort{|a, b| b[1] <=> a[1] }
  500.times{|n|
    e = h[n]
    puts "#{n+1} #{e[1]}"
  }
end

read_and_count(ARGF)
plot2(H)

結果です。横軸が順位、縦軸が頻度です。割ときれいな直線になっていると言えなくもないですね。英語の場合、直線の傾きはだいたい -1 になるそうです。しかし、この場合、直線の傾きは約 -0.734 です。この違いはどこから来るのでしょうか。英語と日本語の違い?

■追記(2006/8/21)。

http://www.jmuk.org/d/?path=2006/08/21#d21t01


2006-08-19

_ Linux で mhtml を見たい

Linux で mhtml(.mht ファイル) を見たくて検索したけど適当な方法がなかった。mhtml の仕様を調べたら、基本的にメールのフォーマットなんで、ruby で何とかできるだろうという事でスクリプトを書いてみた。

~/.rmhtml/ ディレクトリを作ってそこに適当にファイルを展開して、firefox を呼び出すというスクリプト。これを .mht ファイルと関連付ければ、mhtml ファイルを firefox から閲覧することが出来る。要 TMailhtree

#!/usr/local/bin/ruby-1.8
require 'pp'
require 'kconv'
require 'digest/md5'
require 'tmail'
require 'htree'
require "optparse"

Rmhtml_dir = File.join ENV['HOME'], '.rmhtml'

if File.exist?(Rmhtml_dir)
  unless File.directory?(Rmhtml_dir)
    raise RmhtmlError, "#{Rmhtml_dir} exists and is not a directory."
  end
else
  Dir.mkdir Rmhtml_dir
end

class RmhtmlError < StandardError
end

class Rmhtml
  Config = {}
  def initialize(filename)
    @mail = TMail::Mail.load(filename)
    
    if  /text\/html/ =~ @mail.parts[0].content_type
      @main_part = @mail.parts[0]
    else
      each_part(@mail){|e|
        if /text\/html/ =~ e.content_type
          @main_part = e
          break
        end
      }
      raise RmhtmlError, 'main html part does not exist.' unless @main_part
    end
    @mail.parts.delete(@main_part)
  end
  
  def each_part(mail, &b)
    mail.parts.each{|e|
      unless /multipart\/alternative/i =~ e.content_type 
        yield e
      else
        each_part(e, &b)
      end
    }
  end
  
  def get_objects
    @main_html = decode(@main_part)
    ret = []
    @obj_locs = {}
    each_part(@mail){|e|
      filename = filename(e)
      obj = decode(e)
      @obj_locs[location(e)] = true
      ret << [filename, obj]
    }
    return ret
  end
  
  def location(mail)
    mail['Content-Location'].to_s.toeuc
  end
  
  def filename(mail)
    case mail
    when String
      Digest::MD5.hexdigest(mail.toeuc)
    else
      Digest::MD5.hexdigest(location(mail))
    end
  end

  def md5(s)
    Digest::MD5.hexdigest(s.toeuc)
  end
  
  def dir_name
    File.join(Rmhtml_dir, filename(@main_part) )    
  end
  
  def mkdir
    if File.exist? dir_name
      return :exist
    else
      Dir.mkdir dir_name
    end
  end
  
  def decode(mail)
    case mail.transfer_encoding
    when /quoted-printable/i
      mail.body.unpack('M')[0]
    when /Base64/i
      mail.body.unpack('m')[0]
    end
  end
  
  def do_store
    d = mkdir()
    if d != :exist or Config[:f]
      Dir.chdir(dir_name)
      objs = get_objects()
      objs.each{|filename, obj|
        File.open(filename, 'w').write(obj)
      }
      html = change_src_in_main_html()
      File.open(filename(@main_part), 'w').write(html)
    end
    return File.join(dir_name, filename(@main_part))
  end
  
  def change_src_in_main_html
    htr = HTree(@main_html).root
    objs = {}
    htr = change_src(htr)
    ret = ''
    htr.display_xml(ret)
    return ret
  end

  def is_stylesheet_link_tag?(e)
     /link/i =~ e.element_name.to_s and
      /stylesheet/i =~ e.get_attr('rel').to_s and
      /text\/css/i =~ e.get_attr('type').to_s
  end
    
  def change_src(elms)
    objs = {}
    elms.each_child_with_index{|e, ind|
      next unless e.is_a? HTree::Elem
      if src = e.get_attr('src') and @obj_locs[src.to_s.toeuc]
        e = e.subst_subnode( {'src' => filename(src.to_s) } )
      elsif is_stylesheet_link_tag?(e) and href = e.get_attr('href') and @obj_locs[href.to_s.toeuc]
        e = e.subst_subnode( {'href' => filename(href.to_s) } )
      end
      e2 = change_src(e)
      objs[ind] = e2
    }
    elms.subst_subnode(objs)
  end

end

opts = OptionParser.new
opts.on("-f"){|v| Rmhtml::Config[:f] = true }
opts.parse!(ARGV)

rmhtml = Rmhtml.new(ARGV[0])
html = rmhtml.do_store()
system "firefox #{html.dump}"

ちょっと改良。 既存の html ファイルの特定の条件に合う要素だけ入替えるというのは、htree ではやりにくい。他に何かやり方があるのだろうか。


2006-08-20

_ アクセスログにも Zipf の法則

で、懲りもせず、Zipf の法則、つづき。文中の単語の頻度だけでなく、例えばサイトの各ページへのアクセス数に対しても、Zipf の法則が成り立つそうです。Zipf曲線とウェブサイト人気度。おもしろいので実際に試してみました。手元には、この羊堂本舗のアクセスログしかないので、それで試してみました。この日記のトップページと月ページへのアクセスを除外して、ある特定の日付へのアクセスをアクセス数順に並べてみました。

リンク先にある www.sun.com のグラフと比べると、ある順位からの急激な落ち込みも含めて、同じような形になりました。サイトの規模によらず普遍性がありそうです。


2006-08-21

_ はてなブックマークで Zipf の法則は成り立つか?

さて、はてなブックマークのブックマーク数に対して Zipf の法則は成り立つでしょうか。人気エントリーの第1位から第1000位までのエントリーを抽出して、ブックマークしているユーザ数を対数プロットしてみました。横軸がエントリーの順位、縦軸がブックマークしているユーザ数です。

傾きは緩やかですが、Zipf の法則が割ときれいに成立しています。

_ reddit.com の point にも Zipf の法則は成り立つか?

reddit.com の point に対しても Zipf の法則は成り立つでしょうか。はてなブックマークと違って reddit.com では、各ユーザがエントリに対してプラスかマイナスの投票をして、その結果が point として表示されます。単純にブックマークしたユーザ数ではないわけです。all-time top から第1000位までを抽出して、point を対数プロットしてみました。

一次近似としては成立しているかな? もうちょっとちゃんと統計的な検定も必要になってくるような。


2006-08-22

_ はてなブックマークで Zipf の法則、つづき

今度ははてなブックマークの人気エントリーから1万位までを抽出してグラフにしてみました。直線というより、上に凸の緩やかに曲線になっているようです。つまり、テールの部分でべき乗則より速く減衰していることになります。

ちなみに、上位10000エントリーの中で多かったホストと、そのエントリー数は以下のようになります。上位10000エントリーのうち大体 1/10 がはてなダイアリーのエントリーです。

d.hatena.ne.jp980
www.itmedia.co.jp375
japan.cnet.com316
gigazine.net262
blog.livedoor.jp234
itpro.nikkeibp.co.jp160
www.atmarkit.co.jp132
phpspot.org110
www.geocities.jp85
internet.watch.impress.co.jp80
japanese.engadget.com80

ブックマークしているユーザの延べ人数で比べると少し順位が変わります。

d.hatena.ne.jp111303人
gigazine.net48701人
www.itmedia.co.jp45686人
japan.cnet.com31091人
blog.livedoor.jp24795人
itpro.nikkeibp.co.jp21900人
www.atmarkit.co.jp17960人
www.geocities.jp15099人
www.hatena.ne.jp12550人
phpspot.org12084人
www.ideaxidea.com9655人

上位10000エントリーにブックマークしているユーザの延べ人数は1262933です。ユーザの総ブックマークの9%がはてなダイアリーを対象としている計算になります。


2006-08-28

_ W43S

携帯電話を買い替えようと思って、auの新機種発表は何時かと調べたら今日だった。電子コンパスとFelicaが使えて、時計を表示できるサブ液晶がある機種が欲しかったんだけど、W43S が見事に当てはまる。これに機種変更しよう。防水携帯の W42CA はちょっとでかい。

と思っていたら、今使っている携帯電話の電池パックが寿命を迎えた。微妙な時期に電池パックを買わないといけなくなってしまった。


2006-08-30

_ ITmedia の写真への直リンク

ITmedia は画像への直リンクをリファラを見て弾いている。そこで、Firefox 拡張の RefControl をインストールして、image.itmedia.co.jp には常に、

http://plusd.itmedia.co.jp/ 

を送るようにした。

_ livedoor Reader のおすすめがうっとうしい

livedoor Reader のおすすめがうっとうしいので、chrome/userContent.css に以下を追記。

@-moz-document domain("reader.livedoor.com") {
  table[class^="guiderank"],
    table[class^="guiderecom"]{
      display: none !important;
  }
}

2006-08-31

_ file:///etc/hosts などは URL として valid

知らなんだ。RFC 1738の 3.10。日本語ファイル名とかは当然 escape しないといけないけど。


最近のコメント

2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|04|05|
2011|04|
2012|03|07|
2013|01|02|07|
トップ 最新 追記