ログ: 2009/09

シャドールームさんニュース部門移転

若干音速が遅いですが古き良きニュースサイトスタイルのページからブログへ移転されたようで.

ここを読んでいてシャドールーム読んでないタイパーとかいないとは思うんですが,万が一にもいたらモグリと言わざるを得ないので是非購読するといいんではないかと.

ブログになって RSS 配信されてるんで RSS リーダー使うとより便利です.

あとニュースジャンルの画像がついたのもとても良い変化.前のでも並びでわかってはいたけど,一目瞭然.

これだけ業界規模が小さいってのに追っかけてまとめてくれる人がいるってのはありがたいことで, キーボードネタとかタイピング界でのでかいトピックとかは大抵載るので,俺もかなり頼ってます.というかその他の情報源って 2ch くらい*1

  1. mixi とかのコミュから隔絶されているので. []

漢字かな変換のテスト中

2009/09/10 | めも | コメント (0)

といっても自分で実装するわけがなく先人の成果物を弄り回してるだけだけど.

http://dvorak.jp/lab/hconv/

Namazu つながりで知ってた KAKASI と,調べたら出てきた ChaSen と MeCab*1を叩いてみる.

coreserver に自分で入れるかーと思ったら全部デフォで入っていた.妙なところでさすが.

試しもせずに大した精度ないだろうと思っていたんだけど,一番新しくて賢げな MeCab はもちろん,古き良き KAKASI もさすがにこういうことに目的を絞ったソフトウェアなだけはあって頑張ってくれる.綺麗な日本語を突っ込む分には良い精度で機械的に変換できるもんなんだね.

ということがわかった.

もちろんというかあろうことかというか,応用先はタイピングゲームで. 漢字かな交じりの普通の文章突っ込むだけで打鍵対象に出来たら色々面白いかもねという. ブログのエントリがそのまま打鍵対象になるスクリプトだとか,RSS を取りこんでワードセットにするゲームだとか,ニコニコの歌動画のコメントから歌詞っぽい投稿してる人指定するとタイピングゲームになる TypingTube 改とか.

そんなもん書いてる場合じゃないですけどね常識的に考えて.

  1. これらは漢字かな変換っていうかガチに日本語形態素解析する用途で書かれた学術的なもの.言語情報科学に行ってたらお友達になっていたであろう子達である. []

>>700

後から補足するとか完全に後だしじゃんけんなんですけど,

いや,もちろん素の打鍵速度も並のタイパーではまったく敵わないくらい速いんだけど,TWJR 基本常用 ZG とか出しちゃう TW トップランカーの方々なら rkpm は十分勝負できる,っていうか勝てるんじゃね? と思うんですよ.だから,あきうめ氏なら TW でもダントツトップになれるだろうという説は偽ではないかなあとそこそこ論拠ありで思います.

とここに書いた rkpm は「瞬間的な」「出しうる最高値の」 rkpm を意図していた.トプスピって書いたほうが適切だったごめんなさい.

そう訂正した上で当の疑問に関連する俺なりの考えを書いてみるけど,実際にその域に達しているわけではないタイパーの戯言なんで,必要以上に真に受けないでね.

せっかくなんでちょいと遠回りして話を進めるけど,あきうめ氏の凄さについて語れ,と俺が言われたら*1,初速と並べて上げるのは安定感なんだわ.

打鍵フォームの美しさももちろんなんだけど,その成果としての 「(特に物理的にアレな文字列でなければ)打鍵速度が乱れない」 という点での安定感ね*2. そしてさらにその結果としてのミス率の低さ*3

これら個々のスキル的な安定感は,さらに,記録の出方の安定感となって現れるわけ.「ワードによる速度変化小さい」 かつ 「ミス率低い」 から, 「安定して記録を出しやすい」 を導けるのは直感的に明らかでしょ?

そういう意味での安定感が,これまた他タイパーを完全に凌駕してると思うんだよ.

ちょっと統計の単語を借りて言い直せば,「ワードによる速度の分散が小さい」 かつ 「偶然的要素(ミス)による速度の分散が小さい」 より,「記録の分散が小さい」 となり,その分散の小ささと平均の大きさを兼ねるタイパーが今のところあきうめ氏をおいていないんじゃないかと.

俺が思うにタイパー(特にゲーマーを兼ねていないタイパー)が特定ゲームをやり込んだり,ちょこっと考察してみたりする際に欠けてるのがこの分散(記録の安定性)の概念だと思う.

乱打しまくりで運がよければ 700 kpm 出るがしくじると 500 kpm しか出ないって人と,最高記録は 650 kpm 程度だが常に 600 kpm 出せるって人とを,「記録」として表される 700 と 650 で安易に比較はできないということ.こう書くと知ってるよそんなことって感じかもしれないが改めてしっかり意識してみて欲しい.

無限大の時間トライし続けていいならば前者が強いだろうけど,例えばエタイの 1 週間というスパンならば後者の方がいい結果を出す可能性は高い.毎パソなんて一発勝負ならなおさら,というか前者が勝つ見込みはほとんどない.

ニータイパーが TW とかの時間無制限種目で強い理由のひとつもこのあたりにあって,時間をかけまくり試行回数を増やすことで,分散の程度に関わらずかなりいい辺りの値を「記録」とすることができるというわけだ*4

「ユトよりようすけの方が速い,なぜならあっちは何々でどの程度の記録,対してこちらはこんな記録だから」 というような議論からこういった概念はすっぽりと抜け落ちている.「記録」 というのはすなわちその人の実力における最大値付近の値であって,その人の実力そのものではない,ということを意識しなければいけない.記録と実力は高いレベルにおいては同一視してはいけない.

まあ結果的にその人を賞賛する度合いは 「記録」 によって決まっていい*5と思うし,「A より B の方が速く打てるようだ」 という形で推測したり崇拝したりする分にはいいと思うけども,トップレベルとかのそれなりに詰まった状況での考察でこれをやっては前に進めない.試行回数を無限大に増やすことを前提として議論するならともかくとして,現実に出せる記録を語りたいんだから*6

だいぶ話があきうめ氏から逸れた感じだけど,余計な話はしていなくて.例えば俺さんとあきうめ氏のケースが(対極的で)実にわかりやすい.

俺さんが死にもの狂いになってリポ D やって廃人になった結果,常人からすれば半端じゃないほどの記録を出しつつもさらに上がいることに言及して 「ざけんな天才」 とこぼすのはなぜか. エタイであきうめ氏の記録を上回る記録を叩き出しつつもそれほど勝てた気がしていない様子で,憔悴し,さらなる記録を求める声に 「無責任だよてめーらわかったから金をよこせ」*7とつぶやくのはなぜか.ZG 動画やエタイ 700 後半動画とかを気軽に上げようと思えないのはなぜか.

あきうめ氏はエタイ 30 連勝を達成することができて,他のタイパーにまったく実現できそうにないのはなぜか.「俺の連勝記録だけは 200% 破られへんよ」 と連勝記録に自信を持っていたのはなぜか. 多くの動画を面倒がらずに撮影して公開することができたのはなぜか.

良い記録が出せるまでに必要な時間の違い,すなわちは記録の安定度,分散に圧倒的な開きがあるからである.決して最高速度の差なんかではない.

……と書きたいこと書ききったのでおまけのように問題に答える.

「ZG ならあきうめよりスピードは上」 に関しては一番上で書いたように瞬間的なトプスピとしては勝負できるっていうかしろこさんなら勝ってるでしょうという話でした.

でもって TW であきうめ氏がダントツ一位ってわけにはいかないだろうって根拠につけくわえれば,TW では特定の単語を最適化によって打ち込んでいく能力が割と大きなウェイトを占めているので 「安定感」 を武器とするあきうめ氏の打鍵の真価が発揮しづらいこと,再試行がしやすく試行回数が手軽に増やせて,やりこんでいるトップタイパーならば分散を試行回数でカバーして極まった記録を出しているであろうこと*8,など.

エタイ長文に関してはあの長い文章に対して,どのワードでも,どの部分でもほとんどスピードを落とさず機械的にがーっと最後まで打っていけるあきうめ氏の安定感が普通にいかんなく発揮された結果があれで,あきうめ氏の実力からいけば特に驚異的な結果ってほどではないような.

動画解析したあの rkpm を,あの安定感で,最後まで保ち続けられればちょうど 950 とかそんなもんでしょ.その速度域を安定して打てるタイパーはいないっていうことではないかな.TW やり込んでると 「速く打つべき部分を速く打つ」 能力はガシガシ鍛えられていくけど,最適化するほどではないが若干打ちにくい,くらいの部分でもスピード落とさずに行く能力とかはあんまり身につかない気がするし.ワースピ底上げがされないというか.「大船にのった気持ち」 の rkpm が意識しても超えられないので,ネックはそこら辺の能力のような気がする.最高速ではなくて.

さらにそういう能力の方向性のズレに加えて,リトライのしにくさ*9のおかげで他タイパーが低速部分を残しつつも高速部分で稼ぐスタイルで,その安定感のなさをカバーするに十分な回数トライし記録を出すってことができておらず(出す気になれず),あの記録が不動の記録となっているように見える.

という考察が正鵠を射ているならば TW のように Esc で即効やり直せて試行回数を増やしまくったりラップとかの詳細記録で不安定な部分を意識的にフォローしていく環境が整っているなら,トップレベルの人に狙えない記録ではないと思う*10.実際,長文のあの記録より腕試し 800 の方が 100 倍ムズい,と当人らが発言しているわけだし*11

しかし参考にTW 憲法 R の o-ck 氏の BTH を見てみたが ZI で,kpm 900 弱くらい(かな?)なので,この長文考察に関してはあんまり自信ないかも.環境が整ったところで本当に達成可能なのかどうかは実際にすごい人にやってみてもらわないとわからない.すごい人に私がやってみせますと希望されれば yaet に長文モードつけたりくらいの手伝いはしますが.

さらに分散うんぬんについて補足をすると,それってスコア狙いするようなゲーマーの間では(単語はともかく概念は)割と意識されていることなんだよね.エミュでクイックロードしまくれる環境での理論的限界トライアル(いわゆる TAS)と,やり直しのあんまり効かないトライアル(RTA とか)が,種目として完全に分離してるので,理論値と現実的なスコア狙いの違いだのを自然に意識させられるわけだ.

現実的にお披露目しないといけないようなスコア狙いをする場合はどういうプレイスタイルをとって,どういう要素は諦めて,どの程度の点数を落としどころとするのか……そういうことを日々やってる人たちだ.

だからゲーマーであるあきうめ氏が,ああいうスタイルをとって現実的スコアを狙いにいって,実際に目論見が達成されたって事実からして,ゲーマーにとってこのタイパーの議論など,4000 年前に我々が通過した地点だという感じなんではないかと思います.

そんな感じかな.長いよ.いろんなこと考えながらスレみてると言いたいこと溜まっちゃってね.ついでにホテル暇なんだよ.ってことで取り留めなくて申し訳ない.

しかし旅先から 2ch ヲチしてブログで返信とか気持ち悪いことこの上ないな.能登半島から日本海を眺めつつ筆を置くぜ.

  1. 別に信者ではないけど. []
  2. これは例の打トレ動画見るとぼちぼちわかる. []
  3. 打鍵フォームを安定させていて,最適化もしないということは,習熟すればいい動きの数が激減しかつ打鍵中に挟まる思考も減らせるので,正確な打鍵に貢献するはず. []
  4. とこう考えると,タイピストとタイパーの線引きをこの辺りの意識の程度で分けることもできそうな気はする. []
  5. でないとやる気が起きないw []
  6. 最高記録だけ見て語るほうが楽だし,楽しいけどねぇ. []
  7. 超意訳.実際そこまでアレなことは言ってませんすみません皆さんきちんと原文をあたってください. []
  8. に対して,例えばエタイの元気ワードを TW のような錬度でやりこんだ人がどれほどいるだろうか? 推測するに俺さんくらいである. []
  9. 特に特定ワードだけをターゲットにして狙ってると超めんどい.やってられない. []
  10. 一朝一夕に超えれることはないにしろ, 900 とかは出て,そのうち手が届いてくるだろうと. []
  11. 一般のタイパーがこれを聞くと逆のような気がするんだけど,そのギャップは上記してきたような理由によるんではないか. []

Typenist Season 3

closed β1 が今日だとか.

応募したはいいけど予定入ってしまってむりぽだなぁと思ってたら抽選外れてくれたので変な罪悪感抱かずに済んだ.当たった人は開発協力がんばるといいんではないかと思います.

ローマ字入力判定に Tsuikyo 使ってくれたという話なので*1ヒヤヒヤわくわくしてます.

俺もやらないとなぁ.色々.

  1. sf.jp にコミットされてたの見てたので実は前から期待はしていた. []

Twitter やらなくないかも

2009/09/05 | ごみ | コメント (0)

他人とねちょねちょすることが極めて苦手なので敬遠してきたんだけど,iPhone のおかげで便利に利用できるらしいことと,ブログからぐだぐだを一掃したいって事情が噛み合ったのでそのうちに.

このブログの左に実は 2 カラム用意してあって,ひとつ空なのでこんなふうに記事とメニューの間が不恰好に開いたまま放置されてるんですけど,当初そこには Twitter 発言埋める予定だったんだよね.なんでそこまで思い至ってやめたのかは忘れたけど.なんかめんどいことっていうか辛いことがあったんだろうね.

{ 「A けど B」 とか,「B っていうか A だろう」 とかって定型文がお気に入りで,多用してきた } けど,{ ここまで徹底すると何事も言い訳と前フリをしないとしゃべれない { 心の弱い子みたいに見えるよね } っていうか { 多分事実そうなんだろう }}.

A のみと A+B を抽出して文章を読み直すと俺の二面性が浮き彫りになる,という一粒で二度おいしいエンターテイメントを埋め込みだして早半年なんですけど,というのは嘘でそういう意識は全然なかったけど,結果的にそうやって読めるエントリが多いから面白い.

関係ないな閑話休題,まあやるといってもエントリ頭に書いたとおり,特定個人とねちょねちょする気はないのであしからず.

アカウント名は Twitter アカウント名に許される文字で俺のハンドルを表そうとしたときに恐らく最適であるようなもの*1

でもやるやる詐欺なのできっとまだやりません.

  1. このヒントもやりますという発言も何もなしに以前から発見してた人が少なくとも 4 名いるんだけど,さすがだよね,なんというか. []

過去数多の人がやってきたと思うけど

気が向いたので TW のワードセットをごにょごにょ.

Shift_JIS に違いないと決めつけてかかって,このビット列がこういうビット列になるには……と逆行列求めたりしていたんだけど普通に素の Unicode だよっていうね.線形変換できるわけがないんだよ馬鹿が.ひらがなが 0×30 と何かの組になってたら Unicode,という人力エンコーディング判定法を覚えたのでよしとする.なぜか「入力」に見える.前後の文脈が単語読解のヒントとして使われている例.

成果物としては TWEW は完全だと思う.

TWJR は適当にやったので Unicode(UTF-16) で上位 1 オクテットが 0×00 な文字で始まる単語が含まれてなかったりするかもしれないというかする.とりのさんの基本常用と比較した結果 3 語ほど抜けてたお.

漢字に対して読みを振るのもまだ. 別にバイナリごにょごにょでいいけど,せっかくだから KAKASI の精度がみてみたいんだよね,特に慣ことで.ということでぼちぼち.

割とアレというかアレなので,私的な研究目的とか,そういうのでお願いします,と言っておきます*1

  1. 公式にワードセットの扱いについて示してもらえたらタイピング界としては助かるけどねぇ. []

変化についていけない

2009/09/03 | ごみ | コメント (2)

気づくと世間では以下のようなことが起こっていて,そのいずれも俺は察知していなかったことが明らかになった.

  • おおかみかくしが発売されていた
  • Adobe プロダクトの CS4 が出ていた
  • Mac OS X Snow Leopard が出ていた
  • 総選挙が行われ,政権交代が実現していた

趣味の領域のことはさておき,最後はシリアスになるべき問題だと思う. なんかやかましく騒いでるなあとは思っていたんだけど,ちょっと前の都議会選挙のイメージが残ってて,まだやってんのかボケがとかなんかそんな感じで,それと意識されることなくスルーされた.

どうでもいいことって本当にどうでもいいと思ってるので,そんなアンテナ低いと損をするよと頭ではわかっていても社会についていく気が起きない.器の小さな人間としては自分の目の前の,目下の関心領域だけを見つめるので精一杯である.

そんな人間でもある程度食えて楽しめているような気分になれてまあなんとかなるんじゃねって錯覚できる程度に,この社会がうまく構成されてるってことで,俺みたいな人はある意味恵まれていて,ある意味機会を腐らせているんだよな.

選挙くらい行きましょう選挙くらい.行っても白紙投票して義務を果たした気分になって帰宅するだけではあるんだけどさ.

D-JS をもうちょっと実験

2009/09/01 | めも | コメント (0)

引き続き弄ったが気力がなかったので C++ 側ではなく D 側でしこしこ.

先日の D 文字列をばんばん eval して使うという怪しげな使い方をもうちょっと進めて,違和感なく D 関数として js を実行できるようにしてみる.js 関数のインポート,とは微妙に違うけどノリと実現できることは大体そんな感じ.

発想としては js コードを引数にとって D 関数を返すような関数を作ればいい.こういう lambda っぽいことは当の js さんの方が当然得意で,js 書けば

function hoge(code)
{
    return function(){return eval(code);};
}

とかこういうの.D 言語でも言語レベルでデリゲート使った動的クロージャ利用ができるので似たような書き方でいける.

typedef string delegate() JS; // 強い型付け
 
JS jsFunction(string code)
{
    return cast(JS){return v8d.eval(code);};
}
 
JS hello = jsFunction("['H', 'e', 'l', 'l', 'o', "!"].join('');");
hello(); // => "Hello!"

関数リテラルで無名デリゲート書けるので本当に同じノリ.

んでさらに,引数を取れるようにしたい.

事前にソースコードを与えて関数(デリゲート)を作成してるので,その呼び出し時に引数を事前に与えた js ソースの適切な場所に埋め込んでから V8 に食わせるという形.

書式付き文字列ですっきり実装できるんじゃない? とやってみる. js ソースとして

"%s".substr(%d, %d);

とかを与えておいて,

JSsubstr("hoge", 1, 2);

と呼ぶとその内部で

string formatted = std.string.format(`"%s".substr(%d, %d);`, "hoge", 1, 2);

な形で呼び出されて,formatted すなわちここでは

"hoge".substr(1, 2);

が評価されて,めでたく “og” が返ってくるという感じ.

引数の型がまちまちなんでテンプレートかなと若干憂鬱になるが,D にはテンプレートを使わない組み込みの可変個引数関数があるよってことで使ってみる.

typedef string delegate(...) JS; // 強い型付け
 
JS jsFunction(string code)
{
    return cast(JS)(...){
        return v8d.eval(code);
    };
}

ところがこう可変個引数関数へのデリゲートに変更した途端にコンパイルが通らないというか dmd コンパイラが落ちた.v2.014 を使ってて若干古い気もしたので最新の v2.031 にすると通った.

ところがこの可変個引数が割と扱いにくい代物で,各引数にアクセスするにもポインタ経由でお世辞にもエレガントじゃないし,そのままの引数全体をさらに別の可変個引数関数に渡す簡単な方法なんかもない.タプル使えば色々できるのかな,と思うんだけどそうするとテンプレート使っちゃう.

具体的にどう問題になるかというと,スコープのひとつ外にある code を第一引数に,可変個引数デリゲートが受け取った引数全体を第二引数以降の書式指定のパラメータにして std.string.format (sprintf みたいなもん)やらを呼びたいんだけど,うまいこと呼ぶ方法はないもんか,と.

あれこれ試行錯誤して,結局美しい方法が見つからなかったので,気分の悪いローレベルなコードを書いて動かした.

同じような情報を必要としている人が万一いることも考えて詳細を書いておく.

可変個引数関数は,その中で特殊ローカル変数 _arguments と _argptr が使える.前者は型情報を保持するクラス TypeInfo の配列で,後者は引数リストの先頭の void* ポインタ(まあ C の可変個引数関数と似たようなもんではある).

TypeInfo から型のサイズが取れる (tsize()) ので,ポインタ操作してキャストして,これらから各引数を取り出して使うことはできる.が,可変個引数関数にその全てをつっこみ直す簡単な方法は(わから)ない.

じゃあ std.string.format はどう動いてるのかと dmd/src/phobos/std/string.d を見てみると,std.format.doFormat を呼んでいる.そしてその doFormat の引数には _arguments と _argptr がそのまま使えることがわかる.今は書式化ができればいいので,この doFormat を直接呼べばいい.

自分の望む可変個引数の並びをメモリ上に構成し,_arguments と _argptr をそれぞれ更新し,doFormat に渡せば,任意の可変個引数がうまいこと渡せる.

より具体的には,_arguments を走査して現在の可変個引数のメモリ上のサイズを計算し,前時代的な malloc でそのサイズプラス追加したい引数のサイズのメモリを確保,memcpy なりバイト毎に代入なりで現在の可変個引数を新しいメモリ領域にコピー,空いてる領域に望みの追加したい引数を配置,_arguments にも追加した引数の TypeInfo( typeid(型) で取れる)を位置を合わせ正しく追加,doFormat を _arguments と malloc した領域の先頭のポインタで呼び出し,malloc したとこ free,という流れ.

JS jsFunction(string code)
{
    return cast(JS)(...){
        int size = 0;
        foreach (arg; _arguments){
            size += ((arg.tsize() + size_t.sizeof - 1) & ~(size_t.sizeof - 1));
        }
 
        void* argptr = malloc(size + string.sizeof);
        *cast(string*)(argptr) = "{" ~ code ~ "}";
 
        byte* fp = cast(byte*)_argptr;
        byte* tp = cast(byte*)argptr;
        for(int i = 0; i < size; i++){
            tp[i + string.sizeof] = fp[i];
        }
 
        _arguments = typeid(string) ~ _arguments;
 
        string formatted;
        std.format.doFormat((dchar c){formatted ~= cast(char)c;}, _arguments, argptr);
        free(argptr);
        return v8d.eval(formatted);
    };
}

とこれで

JS init = jsFunction("var ts = new Tsuikyo();");
JS add = jsFunction("var w = ts.add('%s');");
JS stroke = jsFunction("w.stroke('%c');");
JS printTimes = jsFunction("for(var i = 0; i < %d; i++) print(w.get%sString());");
 
init();
add("ほげ");
stroke('h');
stroke('o');
printTimes(3, "InputKey"); // => "hohoho"

みたいなことは実際にできるようになった.

引数の数や型の簡単なチェックを入れるとか,細かいことはまだ色々.

D から js を利用する……というよりはメタプロの魔の森に足を踏み入れかけているだけのような気はすごくする.