HootSuite上のさまざまな言語のつぶやきをひとつずつ翻訳するGreasemonkeyスクリプト

Twitter上のさまざまな言語のつぶやきをひとつずつ翻訳するGreasemonkeyスクリプトで使った方法を、HootSuiteでも使えるようにしました。Twitter本家よりもHootSuiteのほうが、画面に表示できる情報が多いので便利だと思います。

HootSuite Translatorインストール

翻訳後のHootSuite

Googleは、翻訳時のエラーメッセージを英語で返します。これまでは、この英語のメッセージも翻訳していましたが、それに失敗すると、何が起きているのかわからなくなってしまうので、翻訳しないことにしました。(使いすぎるとIPではじかれるようです。)

ブラウザ上で動くHootSuiteは、このようにちょっとしたことをすぐに試せていいです。クライアントアプリケーションでは、こういうわけにはいきません。

カテゴリー: コード | タグ: , , | 1件のコメント

13日は金曜日になる運命だった?

13日は金曜日になる運命だったなんていう話があるそうです。

確かに、グレゴリオ暦の1周期(400年間)全部を調べれば、13日は金曜日になるケースが一番多いようです。

でも、それが不吉な日なのだとすれば、一生の間にどれだけ遭遇するかの方が重要でしょう。

例えば、マイケル・ジャクソンの一生(1958.8.25–2009.6.25)の間では、

Needs["Calendar`"]
Tally[Flatten[Join[
   Table[DayOfWeek@{1958, m, 13}, {m, 9, 12}],
   Table[DayOfWeek@{y, m, 13}, {y, 1959, 2008}, {m, 1, 12}],
   Table[DayOfWeek@{2009, m, 13}, {m, 1, 6}]]]]

{{Saturday, 89}, {Monday, 88}, {Thursday, 87},
 {Tuesday, 87}, {Friday, 87}, {Wednesday, 87}, {Sunday, 85}}

となるので(Mathematica)、13日は土曜日になることが最も多かったようです。だからなんだという話ですが、「統計的に証明されている」などと書いてあったので、つい。

カテゴリー: コード | タグ: , | 1件のコメント

もしドラッカーの『マネジメント』を読んだ高校野球の女子マネージャが野球部を甲子園に連れて行ったら

  1. 甲子園は結構簡単にいけるものだと言うことが世間に知れ渡る
  2. 学校・親御さん・地域などが熱心に応援する、などということはなくなる
  3. 甲子園が日本全国共通の関心事ではなくなる

4478012032これは、 「もし高校野球の女子マネージャがドラッカーの『マネジメント』を読んだら」というようなタイトルの本(以下もしドラ)がベストセラーになるような状況ではありません。

実際は、こういうことはないので、もしドラは、タイトルだけで売れる本になっています。

ということは、もしドラは、もしドラで描くような事態が起こりえないということに依存したお話なのです。

なんて考えちゃう人は、著者のトラップその4にはまっています。

ドラッカーにならうと、こんな感じになるのでしょうか。

出版社とは、一体なんでしょう。出版社とは何か? 出版社の事業とは何か? 何であるべきなのか?

出版社って、出版をするための組織じゃないの?

(違うらしい)

本当に、「顧客」とは一体「誰」なんだろう?

(本を買う人。あるいは読む人?)

出版社のすべきことは?

(客に本を売ること、あるいは本を作ること?)

出版社の定義は「顧客に本を売るための組織」あるいは「本を作るための組織」?

目標は?

(ベストセラー)

顧客は何を買いたいか?

(意外な組み合わせ、高校野球とドラッカー。だじゃれ、野球部のマネージャと一般的なマネージャ。萌え。気の利いたタイトル? 「ドラッカーくらい知ってるよね」というプレッシャーの克服。感動?)

(「ある人の弱点を理由にして、仕事を任せるのを止める」という「ある人の弱点を理由にして、仕事を任せるのを止める」ということについて)『マネジメント』には、これについてなんて書いてあっただろう? これについて、何か答えはなかったか?(p. 222)

4478410232という問いへの解答は紹介されていないので、これが気になる人は、はじめからオリジナルに当たった方がいいかもしれません。

以下略。

タイトルがとてもいいと思いました。

カテゴリー: | コメントをどうぞ

去年はこんなに暑かったっけ?

とか「7月ってこんなに暑かったっけ?」というセリフをよく聞いたのですが、実際のところどうだったのでしょう。夏暑いのはあたりまえなので、気のせいのような気もしますが。

まずは、「weather tokyo 2008 july」

次に「weather tokyo 2009 july」

最後に「weather tokyo 2010 july」

(Wolfram|Alphaのデータを信用して)結果を見ると、最低気温・最高気温ともに今年の7月は高かったということがわかります。「たった1度なんかだから、暑いと感じるのは気のせいなんじゃない」かとも思いますが、(温度変化のパターンがだいたい同じだとすれば)グラフが上に1度平行移動したと思えば、やっぱり暑かったと言えるでしょう。

みんな大好きWolfram|Alphaでした。

カテゴリー: インターネット | タグ: | コメントをどうぞ

テキスト処理のための正規表現に計算理論はあるのかな

なるほど。これはおもしろい。

正規表現で素数判定

「C言語で素数判定」や「Rubyで素数判定」はそうでもないのに、「正規表現で素数判定」と言われるとおもしろいと思うのはなぜだろう。

4320122070計算の理論について勉強したことのある人は皆、正規表現で素数を記述することはできないことを知っている(たとえばSipser『計算理論の基礎』を参照)。だから、「正規表現で素数判定」と言われると、一瞬不思議な感じがするのだろう。

正規表現の表現力はもともとそんなに高くない。だから、

正規表現とは元々数学の概念だけあって、数学の問題を解くのにもってこいですね!(regexp – でエラトステネスのふるい

なんていうのは、かなりミスリーディングなジョークだ。

とはいえ、テキスト処理のための正規表現は、計算理論における正規表現よりもかなり強力なものになっている。その原因の一つに、括弧でくくられた部分文字列を参照するために「\数字」という記法が導入されたことがあり、今話題にしている素数判定を可能にしたのも、この記法だ。

大事なことだから繰り返す。計算理論の正規表現では、素数判定はできない。テキスト処理の正規表現では、素数判定ができる。

素数判定というと、次のようなものをそうぞうする。

sub isPrime {
  my $n=shift;
  my $imax=sqrt($n);
  for (my $i=2; $i<=$imax; $i++) {
    if ($n % $i == 0) { return 0; }
  }
  return 1;
}

たとえば、isPrime(5)を評価すれば、5が素数かどうかがわかる。

これと同じことを、1を5個並べた文字列に対するマッチング「’11111′!~m/^1?$|^(11+?)\1+$/」で調べられる。

なるほど。これはおもしろい。

さて、素数判定には、「エラトステネスのふるい」という有名な方法がある。

「2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20」という数列が与えられたときに、2の倍数を消去、3の倍数を消去、・・・としていくと、素数列つまり「2,3,5,7,11,13,17,19」が残る。

今話題にしている記法では、「11,111,1111,11111,111111,1111111,11111111,111111111,1111111111,11111111111,111111111111,1111111111111,11111111111111,111111111111111,1111111111111111,11111111111111111,111111111111111111,1111111111111111111」という文字列が与えられたときに、「11,111,11111,1111111,11111111111,1111111111111,11111111111111111,1111111111111111111」が残るといい。

正規表現でエラトステネスのふるいはさすがに無理かな(正規表現で素数判定)

という問いで期待されている解答は、次のようなものなのだろう。

これと同じことを、「・・・」という文字列に対する置換「’・・・’=~s/???/???/」で調べられる。

最初に思いついたのはこんなもの。

#!/usr/bin/perl -w
use strict;
use warnings;

my $max=shift || 20;
my $nums=join ',',map {'1' x $_} (2 .. $max);
print "$nums\n";

while ($nums =~ m/(^|,)(1+)(,|$)/) {
  printf "$2,";
  $nums=~s/(^|,)($2)+(,|$)/,/g;
}

これは、理想の形式からはほど遠い。whileなんてものを許したら、表現力が正規表現と比べてどうなのか、まったくわからなくなってしまうのだから。

カテゴリー: コード | タグ: , | コメントをどうぞ

たった600円でオライリー本をKindleで読む。自動化。

「たった600円でオライリー本をiPadやKindleで読む。すてき。」という記事がすてきです。100冊買っても6万円って。でも、作業がちょっと面倒です。

iPadな人は、「perl – O’ReillyのiPhoneアプリ本からepubをぶっこぬく」にあるスクリプトを使えば、処理の大部分を自動化できます。

Kindleな人は、もう一手間かかるのですが、やはりスクリプトを書いて自動化しておきましょう。(参考:Kindle形式で目次を表示する。epubとの違い。Kindle用の目次を生成するスクリプトを書いた。

以下の作業を一つのスクリプトにまとめます。

  1. toc.ncxからのネームスペースの削除
  2. toc.htmlの生成と登録
  3. iPad用のepubの生成
  4. Kindle用のmobiの生成

準備

perl, zip, unzip, kindlegenにPATHを通しておいてください。Windowsの人は、Cygwinを使うといいでしょう(デフォルトではzipは入らないかもしれないので、インストール時に選択してください)。

使い方

perl ipa2mobi.pl ipaファイル名

Kindleで読み込んだところ

ipa2mobi.plのコード

#!/usr/bin/perl -w

#------------------------------------------------------------------
print "Step 1: http://blog.livedoor.jp/dankogai/archives/51484907.html\n";

use strict;
use warnings;
use File::Basename;
use File::Path;

sub clean{
    File::Path::rmtree('Payload');
}

my $src = shift;
#die "usage:$0 src.ipa [dst.epub]" unless -f $src;
die "usage:$0 src.ipa" unless -f $src;
#my $dst = shift;
my $dst = basename($src);
#if (!$dst){
#    $dst = basename($src);
    $dst =~ s/\w+$/epub/;
#}

system qw/unzip -q/, $src, qw/-x iTunes*/;
die $! if $!;
my $app = <Payload/*.app/book>;
clean and die "No book found in the archive" unless $app;
chdir $app;
my $updir = '../../..';
#system qw/zip -q0X/, "$updir/$dst", 'mimetype';
#system qw/zip -qXr9D/, "$updir/$dst", qw/ META-INF OEBPS/;
#chdir $updir;
#clean;
#system qw{open -a /Applications/iTunes.app}, $dst;

#------------------------------------------------------------------
print "Step 2: Modify toc.ncx\n";

chdir 'OEBPS';

rename 'toc.ncx', 'toc.bak';
open(IN, 'toc.bak');
open(NCX, '> toc.ncx');

while (<IN>) {
  $_ =~ s|<(/{0,1})ncx:|<$1|g;
  print(NCX $_);
}

close(IN);
close(NCX);
unlink 'toc.bak';

#------------------------------------------------------------------
print "Step 3: Create toc.html\n";

use XML::LibXML;

if (! -f 'toc.html') {
sub processNavPoint() {
  my $node=shift;
  my $depth=shift;
  if ($depth==0) { print HTML '<h1>'; }
  printf(HTML "<a href='%s'>%s</a>",
    $node->findvalue('content/@src'),
    $node->findvalue('navLabel/text'));
  if ($depth==0) { print HTML "</h1>\n"; }
  my @navPoints=$node->findnodes('navPoint');
  if ($#navPoints!=-1) {
    print HTML "<ul>\n";
    foreach my $navPoint (@navPoints) {
      print HTML '<li>';
      &processNavPoint($navPoint,$depth+1);
      print HTML "</li>\n";
    }
    print HTML "</ul>\n";
  }
}

  open(HTML, '> toc.html');
  binmode(HTML, ":utf8");
  print HTML <<EOF;
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html>
<head>
<title>Table of Contents</title>
</head>
<body>
EOF
  my $parser = XML::LibXML->new();
  my $toc = $parser->parse_file('toc.ncx');
  &processNavPoint($toc->findnodes('/ncx/navMap/navPoint'),0);
  print HTML '</body></html>';
  close(HTML);

#------------------------------------------------------------------
print "Step 4: Modify content.opf\n";

  rename 'content.opf', 'content.bak';
  open(IN, 'content.bak');
  open(OPF, '> content.opf');

  while (<IN>) {
    print(OPF $_);
    if (/<item id="cover"/) {
      print(OPF '    <item id="toc" href="toc.html" media-type="text/html"/>'."\n");
    }
    elsif (/<itemref idref="cover"/) {
      print(OPF '    <itemref idref="toc" linear="no"/>'."\n");
    }
    elsif (/<reference href="cover.html"/) {
      print(OPF '    <reference href="toc.html" type="toc" title="Table of Contents"/>'."\n");
    }
  }

  close(IN);
  close(OPF);
  unlink 'content.bak';
} # end of if (! -f 'toc.html')

#------------------------------------------------------------------
print "Step 5: Create ePub\n";

chdir '..';
system qw/zip -q0X/, "$updir/$dst", 'mimetype';
system qw/zip -qXr9D/, "$updir/$dst", qw/ META-INF OEBPS/;
chdir $updir;
clean;

#------------------------------------------------------------------
print "Step 6: Create mobi\n";

system qw/kindlegen/, "$dst";

問題

  • 目次の位置が本の最後になってしまいます(ジャンプすればいいのですが)
  • perlの作法、よく知りません。

って書いておけば、誰かがきれいなスクリプトに直してくれるはず。

ゆっくり読みたいときは目に優しいKindleが、開発中にリファレンスとして使いたいときは描画の速いiPadがいいと思います。iPhoneで読むのは大変だと思います。

オライリーとしては、情報弱者を食い物にするのと情報強者にサービスするののバランスを調整することで、利益が最大になればいいのでしょう。

追記:toc.htmlがすでに存在しているときには、step 3, 4を飛ばすようにしました。

追記:目次が最後になってしまう問題が解決しました(コメントに感謝)。

カテゴリー: コード, | タグ: , , , , | 7件のコメント

隣の家の少女

459402534Xジャック ケッチャム著, 金子 浩訳『 隣の家の少女』(扶桑社, 1998)

ベランダに放置された少女が、「ここで寝る。おやすみなさい」と言って死んだ事件があった。虐待は絶えない。この小説では、両親を交通事故で亡くした少女が、引き取られた家で虐待され、レイプされ、殺される。虐待を先導するのはその家の女主人で、子どもたちがそれに荷担する。隣に住む主人公の少年は傍観者である。ベランダの少女の心を想像するには足りないが、子どもを精神的に攻撃することの容易さと、傍観者でいることの怖さはうまく書かれている。

カテゴリー: | 2件のコメント

ポスト複製芸術時代のカデンツァ

4575823686日本フィルハーモニー交響楽団の東京定期演奏会を聴く。広上淳一氏指揮、ファジル・サイ氏のピアノでベートーヴェン・ピアノ協奏曲第3番。カデンツァはファジル・サイ氏のオリジナル。本当に即興で演奏されるカデンツァには劣るかもしれないが、オリジナルというだけでも、聴く方はかなりの緊張を強いられる。21世紀はポスト複製芸術だ、というようなプレトークがあった。録音された演奏に慣れた私にも、別の楽しみがあるか。

カテゴリー: 音楽 | 2件のコメント

横井軍平ゲーム館

4845910500横井 軍平, 牧野 武文『横井軍平ゲーム館 RETURNS ─ゲームボーイを生んだ発想力』(フィルムアート社, 2010)

ゲーム&ウォッチやゲームボーイなど、往年の任天堂を代表する商品を開発した横井軍平へのインタビュー。安く量産できるようになったものを、本来の目的ではないことに使おうとする彼の信条は、「枯れた技術の水平思考」と讃えられている。しかし、電卓の普及によって枯れた液晶をゲームに使った時代と違い、今日のゲーム業界には、技術を牽引するという役割もあり、その期待を背負って勝負している人たちも讃えたいと、私は思う。

カテゴリー: ゲーム, | コメントをどうぞ

Twitter上のさまざまな言語のつぶやきをひとつずつ翻訳するGreasemonkeyスクリプト

Twitterは言葉の通じる相手とのコミュニケーションツールとして使うのが一般的ですが、大量の情報が集まっているわけですから、何か他のことにも活用してみたいと思うわけです。

何らかのキーワードを指定して、それを含んだつぶやきを検索してみる、なんていうことは、試したことのある人も多いでしょう。例として、「mathematica」というキーワードで検索した結果を挙げてみます。英語やスペイン語、中国語、ポルトガル語などがあるようです。よくわかりませんが。

「mathematica」というキーワードで検索した結果

日本語と英語はともかくとして、他の言語はよくわからないので、とりあえず、機械翻訳にかけてみたいところです。精度はともかく、使い勝手は向上している機械翻訳ですが、Twitter上で使うには、少し工夫が必要です。というのも、Twitterにはさまざまな言語のつぶやきがあるので、まとめて翻訳するわけにはいかないからです。

Google Chromeという親切なブラウザは、ユーザが設定した言語以外で書かれたページを、読みやすいように翻訳してくれます。しかし、元の言語を一つに決めなければならないので、Twitterでは失敗します。下の例では、英語以外のつぶやきは翻訳できていません。

Google Chromeの翻訳結果

ですから、Twitterのつぶやきは、ひとつずつ翻訳しなければならないのです。そのためのGreasemonkeyスクリプトTwitter Translatorを書きました。

インストール方法

  1. Firefoxをインストールする
  2. Greasemonkeyをインストールする
  3. Twitter Translatorインストールする

つぶやきをひとつずつ翻訳した結果

翻訳先の言語は、ブラウザの言語設定で決まります。ふつうにFirefoxを使っている人は、特に何か設定する必要はないでしょう。言語設定を変更したい場合は、Google を使ったなんちゃって地域化で紹介したQuick Locale Switcherを使うといいでしょう。

各種Twitterクライアントも、つぶやきを翻訳する機能を入れておいてほしいものです。(TweetDeckは、フォントをちゃんと設定できるようにすることを先にお願いします。)

追記:HootSuite上のさまざまな言語のつぶやきをひとつずつ翻訳するGreasemonkeyスクリプト

カテゴリー: コード, 言語 | タグ: , , | 2件のコメント