インターステラ―

話を広げるだけ広げて、いったいどうやって最後をまとめるのだろうかと心配しながら観ていたら、最後は「全部夢でした...」と肩すかしを食わされたのが、同じ監督クリストファー・ノーランの「インセプション」という映画だった。相対性理論とか4次空間だとか5次元空間だとか時空の地平線だとかブラックホールとかワームホールとか持ち出して振り回すと、話はなんでも有りになってしまう。この映画も禁じ手のエンディングだ。状況設定は面白いが、不要と思われるエピソードも延々とありの3時間弱。相変わらず、映像デザインは凝っており好感が持てるのだが、もう少しストーリを整理して欲しい。再提出!

楽天テクノロジーコンファレンス2013

昨日、品川シーサイドの本社で開催された楽天テクノロジーコンファレンスに参加して来た。以前に比べて運営が洗練されてきており、これは経験の賜物と思う。松岡先生のツバメプロジェクトのお話しは感動的であった。戦う姿勢に溢れており聴衆に勇気と刺激を与える。松岡先生にはJobsのようなカリスマを感じる。アワード受賞語のスピーチの結びの句を紹介したい。

20年後、いまのアマゾンの全データセンターが持つ計算パワーが、1枚のタブレットコンピュータに入る。その時に向けて何をすべきか? 一緒に競争しましょう!

会議の公用語は英語である。日本人の話す英語は、一部を除いては稚拙だ。しかしその下手な英語でも頑張っている若者達に刺激を受けた。かつて私が学生時代に通った夜間の英語学校でも、校舎内は日本語禁止で、日本語を話したら千円の罰金というルールだった。授業後に立ち寄った喫茶店でも、日本人どおしで必死に英語で話していたこと思い出す。会議の参加者に混ざる外国人と日本人の参加者が自然に融和している光景を目にして、楽天の社内英語化は着実に定着し成果を上げていることを実感した。

終戦のエンペラー

題材が面白い.歴史に対する興味を喚起してくれる良い映画であった.私は1958年生まれであるが,私の生まれるほんの13年前に,日本がこういう状態であったという事実に驚愕する.連合国による統治はその後7年間続き,日本が主権を回復するのは1952年で,私が生まれたのはその僅か6年後である.だが私の幼少の記憶には戦争や占領時代の面影は全く存在しない.これは何故か?この時代になにがあったのか,もっと歴史を勉強しないといけないと強く強く思う.

ところで,この映画は米国でどのくらいの人に観られたのか興味があったので調べてみた.

2013/8/11現在,過去一年間のランキングでは興行成績は以下のとおり.(http://www.boxofficemojo.com

順位 タイトル 収入 館数 公開日 終了日
154位 終戦のエンペラー 3.3億円 311館 2013/3/18 2013/6/13

ちなみに1位は「アイアンマン3」で407億円,4,253館であります.(こちらはまだ上映中なので最終成績でない)

WebSocket URIの謎

疑問

RFC6455ではwebsocketのURIスキームが定められている。これは通常のURIと同じ形式で、たとえばこんな風に記述される。

ws://example.com:3000/foo

ところでWebSocketという言葉の印象から判断すると、これはソケットであるからホストアドレスとポート番号さえ指定すれば、接続先は一意に決まってしまいそうな気がする。そうするとこのURIの最後にくっついているpath部分"/foo"は何に使うのだろうか?


調査

JavaScriptでコードを書いてみる。クライアンからサーバへの接続リクエストはこのようになる。

var ws = new WebSocket("ws://example.com:3000/foo");

この接続リクエストを受けるサーバは、こんな風になる。コードは省略しているが、このWebSocketServerオブジェクトは3000番のポートでlistenしている。

webSocketServer.on('request', function (req) {
    console.log("Request resource: " + req.resource);

クライアントから接続要求があると、WebSocketServerオブジェクトの requestイベントのハンドラにはWebSocketRequestオブジェクトが渡ってくる。WebSocketRequestのresourceプロパティにクライアントが指定したURIのpath部分が入ってる。HTTPからWebSocketへ昇格するときのHTTPヘッダのやりとりを観察すると以下のようになっている.

クライアントからのリクエスト

GET /foo HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:22.0) Gecko/20100101 Firefox/22.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Sec-WebSocket-Version: 13
Origin: http://localhost:3000
Sec-WebSocket-Key: VSDuTDuniJF2SmiyhVPenA==
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket

サーバからのレスポンス

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 7TcssaQZrihZ2PPVX4P5Yd3sQfI=
Origin: http://localhost:3000

結論
クライアントからの接続リクエストのHTTPのハンドシェイクのGETメソッドの引数としてpathが渡っている.つまりWebSocketのサーバーは,これをみていろいろ挙動を変えられるということになる.WebSocketとは,ソケットという名前から(原始的なソケットという)誤った印象を持ってしまいそうだが,メッセージのフレームをちゃんと管理してくれるとか,アプリケーションを作る上で便利な機能がそろっているのであった.

[参考URL]

https://github.com/Worlize/WebSocket-Node/wiki/Documentatio

風立ちぬ

ラストでの「自分のつくった飛行機に乗った人間は誰も帰って来なかった」という台詞が胸に染み入る.技術者は時代に関係なく生きられないものだろうか? という思いが頭をよぎった.時代とは無関係に美しいものを作りたいという願い.これは技術者の身勝手な思いなのだろうか.

長引く不況,震災,右傾化,解決の見通しが立たない原発事故など.この映画で描かれる時代と現代がもつ不安感は見事に重なる.はたして,この国は戦争へ向け歩みを進めるのか.

冒頭の蚊帳と畳の緑色が美しく,機関車の走る姿,飛行機の飛ぶ姿の力強さ,優雅さは名人芸.いままでのジブリのファンタージと同列で比較するのは無理があるが,わたしの中で,この作品は宮崎アニメの頂点となった.

[計算機]CodeIQのピッグデータ問題の回答

CodeIQの結城さんの「《ピッグデータ》に負けないで!」https://codeiq.jp/ace/yuki_hiroshi/q303 に応募した際の回答を貼っておきます.結果,評価5 ベスト・ピッグデータ賞(結果が正しく技術メモも十分な解答)をいただきました.成績の分布は下のとおりだそうです.

評価5: 38
評価3: 0
評価1: 15
合計: 53

このソート方法にはバケットソートという名前がついていることは知りませんでした.現在,私のところへはスカウトは来ていない.:-)



[技術メモ]
209679232 <--これが答え

Date: 2013/5/3

1)答えを求めるのに必要なデータ件数は 100*(2^30)件である.一件あたりのデータサイズは2byteなので,最低でもデータサイズは200Gバイトになる.

2)このデータをソートしなければいけない点を考慮すると,このデータをメモリ上はおろか,外部ファイルに持つのも簡単ではない.したがって別のアプローチを考える.

3)データの値は2byteなので,この値をキーとし,値を発生件数とするHashテーブルを作成して処理を行う.これによりソートを行う必要は無くなくなる.

4)処理を2フェーズに分け,前半のHashテーブルの作成はC(ソースコード1)で行い,結果をCSVファイルに出力する.後半の総和を求める部分はRubyソースコード2)で記述する.Cを採用したの高速化のため,Rubyを採用したのは,記述のしやすさが理由である.なおCの処理では,SHA1の呼び出し回数をを減らすため,2重ループにしてある.Cの処理部分は,下記の環境で142分かかった.

5)検証はサンプルデータに対して行っているが,充分という気がしていない.もう少し考える必要がありそうだ.出題者がどのように正解を検証したのか非常に興味がある.

6)問題の理解のため,最初にHaskellソースコード3)でプロトタイプを作成した.これはサンプルデータでは動くが,実課題のデータサイズでは遅すぎて使えない.

[使用環境]
MacOS 10.7.5
CPU 2.4Ghz Intel Core 2 Duo
メモリ 4G
gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)

[感想]
簡単と思い始めましたが,予想以上に手こずり,2日程ゴールデンウィークをつぶしてしまいました.面白い問題をありがとうございました.

[ソースコード1]

#include 
#include 
#include 
#include 
#define COMMON_DIGEST_FOR_OPENSSL
#include 
#define SHA1 CC_SHA1

#define COUNT 100 * pow(2,30)

#define SKIPS pow(2,24)
#define DATA_MAX pow(2,16)

int64_t data[(uint16_t)DATA_MAX];

int main(){
  printf("start\n");
  uint64_t i;
  uint32_t j;
  int k,k2,value;
  char sbuf[256];
  unsigned char digest[40];

  // init data array
  for(j = 0; j < DATA_MAX; j++){
	data[j] = 0;
  }
  printf("array init done\n");

  i = COUNT;
  printf("limit:%llu\n",i);
  for(i = 0;; i+=1){
	sprintf(sbuf,"%llu",i);
	SHA1(sbuf,strlen(sbuf),digest);
	for(k=0;k<10;k++){
	  if(COUNT <= (i*10)+k) goto done;
	  value = digest[k*2]*256 + digest[k*2+1];
	  // printf("%llu: %d\n",i*10+k,value);
	  data[value]+=1;
	}
  }
 done:
  for(j = 0; j < DATA_MAX; j++){
	if (0 < data[j]) printf("%d,%llu\n",j,data[j]);
  }
}

[ソースコード2]
#!/usr/bin/ruby

count = 100*(2**30)
skip = 2**24
sum = 0
accum_count = 0
k = 0

while l = gets
  data = l.chop.split(',')
  value = data[0].to_i
  n = data[1].to_i
  accum_count += n
 
  while k < accum_count
    sum += value
    puts k.to_s + " add:" + value.to_s
    k += skip
  end
  break if count <= k
end
puts sum

[ソースコード3]
import Data.Digest.SHA1
import Codec.Binary.UTF8.String
import Numeric
import Data.List

getdata :: Integer -> Integer
getdata index = 
  let 
    divisor = 10
    q = div index divisor
    r = mod index divisor
  in
   getdata_2 q r
   
getdata_2 :: Integer -> Integer -> Integer
getdata_2 q r =
  let str = int2hexstring (Data.Digest.SHA1.toInteger $ hash $ encode $ show q) 
      hexarray = string2hexarray str
  in
   getdata_3 hexarray r
   
getdata_3 :: [String] -> Integer -> Integer
getdata_3 s r =
  let r2 = fromIntegral(r * 2) 
      n0 = hex(s !! r2)
      n1 = hex(s !! (r2 + 1))
  in
   (n0 * 256) + n1
   
getsign :: Integer -> Int -> Integer
getsign count skips =
  let d = sort $ makedata count
  in calc_sum d skips
     
calc_sum :: [Integer] -> Int -> Integer
calc_sum d skips =
 sum $ calc_sum_filter d skips

calc_sum_filter :: [Integer] -> Int -> [Integer]
calc_sum_filter d skips =
  let x = (head d) 
  in 
   if *1 ++ str
     
genzeros:: Integer -> String
genzeros 0 = ""
genzeros n = "0" ++ (genzeros (n-1))

string2hexarray :: String -> [String]
string2hexarray (x1:x2:) = [x1:x2:]
string2hexarray (x1:x2:rest) = (x1:x2:[]):(string2hexarray rest)
                               
hex :: String -> Integer
hex s = read ("0x" ++ s) :: Integer
                            
main = do
  let 
    count = 107374182400
    -- count = 100
    skips = 16777216
    result = makedata count
  mapM_ (putStrLn . show) result

*1:length d) <= skips) then x:[] else x:calc_sum_filter (drop skips d) skips makedata :: Integer -> [Integer] makedata 1 = [ getdata 0 ] makedata n = getdata(n-1):makedata(n-1) int2hexstring :: Integer -> String int2hexstring n = let str = showHex n "" r = 40 - (Prelude.length str) in if r == 0 then str else (genzeros (fromIntegral r