「pp」を含む日記 RSS

はてなキーワード: ppとは

2011-11-10

運転履歴証明書の効力が永年化したという報道から

何で管轄が全く違う部署で法的に効力のある身分証明書をポンポン出しちゃうかな?

他の国ではありえない数の身分証発行国だぞ。何でこうセキュリティ面で進歩しないのかね(むしろ住基カード導入時の目標から大幅に後退している)。

折角住民基本台帳カードという戸籍証明其の物を表した最強の身分証明カード(このレベルで効力を持つのPPのみ、しかし期限があるのは周知の通り)があるのに、行政サービスを受ける為のカードが複数あるというのは事務手続きの煩雑化を招く上に、個人の使わない多くの身分証に対する管理煩雑になり、結果偽造されても気付かない可能性も出てくる。

住基カードに切り替えるように勧めればいい話で、労力をこんな事に費やすなら、もっと住基カード機能を強化してくれ。

2011-03-25

暫定基準値がおかしい

水道水の暫定基準値って何が根拠?

WHO飲料水水質ガイドラインpp.201-204によると

一般成人による放射性核種の摂取に関する線量換算係数

放射性核種 線量換算係数(mSv/Bq)
セシウム134 1.9*10^(-5)
セシウム137 1.3*10^(-5)
ストロンチウム90 2.8*10^(-5)
ヨウ素131 2.2*10^(-5)

およびガイダンスレベル計算

GL = IDC / (hing * q)

GL飲料水中の放射線核種のガイダンスレベル(Bq/L)

IDC:個別線量基準。ここでは 0.1(mSv/y)

hing:成人による摂取の線量換算係数(mSv/Bq)

q:飲料水の年摂取量。ここでは730(L/y)

を用いて計算(有効数字2桁)すると

放射性核種 GL(Bq/L)
セシウム134 7.2
セシウム137 11
ストロンチウム90 4.9
ヨウ素131 6.2

になるんだけど。

2010-10-09

ポケモンプレイして感じたやっぱ任天堂の本気はすげぇ

かれこれ、初代ポケモングリーンをやったのが最初最後だったから、今回ポケモンブラックプレイしたのはもう12年ぶりくらいなんだろうか。

いろいろ感じたことは、ポケモンとは今までのRPG集大成だということだ。

(1)自由なパートウエイトが大きい

とりあえずエンディングまでは辿りついた。

まだまだ冒険は終わりではないらしい。。

これからは順不同で自由度の高い旅が用意されているみたい。

出会いを求め、伝承を辿り、新たな発見を求めて冒険がずっと続いていく。

近作のポケモンコンピュータRPG史上初めて導入された画期的な要素ではないけれど、このエンディング後のパートが大きいのは特徴的だ。

一本道の必須パート+エンディング後(あるいはエンディングの前から)に自由なパート

の2パート構成は最近RPGにはよくある。

例をあげれば、クリアした後も、エンディング後にいけるようになる隠しダンジョンや、クエストとよばれる小冒険を続けることでストーリーテリングの楽しさが去った後もゲーム面白さを維持できる。

もともと、自由なパートが置かれる以前でもPG(ここではドラクエに代表されるRPG)の魅力の1つは探索だった。

近作のポケモンは後半のパートがかなり多い。

今回、ポケモンブラックホワイトエンディングまでに巡ることが出来る町はマップにある町のたった3/4ほどだ。

ダンジョンに至っては半分くらいストーリーと無縁だ。

もちろん、通信機能を使ったクエストも用意されている。

(2)キャラ育成要素と感情移入しやすさのバランス

ドラクエでいえば3、FFでいえば5、自由度の高い育成要素を加えたゲーム面白い

反面、キャラ自由度を持たせることは、人格定義しにくくなる。

ドラマパートでは勇ましいセリフを言うけれど、戦闘シーンでのジョブ遊び人だとか、移動シーンでは鎧を着てるのに戦闘シーンでは魔法使いローブを着ているとか。

か弱い女性という設定なのにパーティ最高火力だとか。

その点で、ポケモン完璧だ。

どんなにポケモンを鍛えようと、どんなポケモンを育てようと、主人公の人格違和感はない。

パーティメンバー過去の設定をつけないという意味では、DQ3のルイーダの酒場システムWizのが古いしギルガメッシュ酒場というべきか)と同じのはずだが、ポケモンのほうが自然キャラ感情移入が出来る。

流石にそこは人間と獣の差、獣はペットを飼う感覚で従えることができるが、共に冒険する仲間にはそれぞれ世界にたった一つの冒険する理由が欲しい。

戦闘員と主人公を全く切り離し、戦闘員を非人間にすることで完璧な解決を図ってる。

とはいえ、これだってポケモンが初の試みになるかは微妙だ。

たとえば昔から女神転生では似たシステム採用されてた。

(3)狭い世界

RPGにおける世界の広さは、スーパーファミコン時代が一番広かったと思われる。

主人公が住む世界地球規模(船や空を飛んで一周できる)で、さらにもう1つ、あるいは二つ同じように地球規模の異世界次元をまたいだり時空をまたいで存在し、同じように人の営みが用意されていた。

ところが、それ以降は世界の広がりはない。

むしろ、ある外界から隔たった特定地方舞台にすることが増えてきた。

おそらく、僕らの住む現実世界のようにいろんな人がいて、いろんな思想、派閥存在する世界の諸問題は、魔王を倒せば解決するような単純なものではないからだ。

ポケモンもこの流れを踏襲してる。

狭い、人の繋がりの密な世界の温かさ、かといって冒険が不自由なわけではない。

世界が狭いからといって、すぐに退屈してしまうことはない。

僕が子供の頃に近所の廃屋や林を探索していたときには退屈さを感じなかったように。

(4)古きよきターン制

ポケモン廃人パラメータからダメージ計算できるように、極めて厳格なルールで動いている。

パラメータと行動の結果がほとんど予想可能なまでにすることで、カードゲームのような戦略性が生まれている。

そこに、僅かに1つ2つ、(僅かであるのがミソだ)乱数で決まる要素を加えることで、興奮が高まる。

テーブルトークRPGから伝統的な古きよきターン制だ。

しばらく気付けなかったが、風来のシレンのようなダンジョンRPGに通じるものがある。

なにを、何回、どういう順番で、行うか、それをプレーヤーに考えさせる。

MP制でなくPP制にしたのもそのせいだと思う。

もちろん、これが対戦という状況においてさらに頭脳戦の楽しさとなるだろうことは想像に難くない、

(5)通信要素

思えば、初代ポケモングリーンレッドの2バージョンを用意することで、通信なくしてコンプリートできない仕様にしたのは画期的だった。

最近だと、インターネットにより携帯機でなくとも通信は可能になったけれど、ネットワーク利用で面白さを倍増させることに関しては、これ以上のゲームはなさそうだ。

面白さを倍増と書いたが、累乗といっていいかもしれない。

DSのためのソフト、いや、ポケモンのためのハードこそDS

ラブプラスDSの特性を最大限生かしたゲームとか言う意見を聞いたけど、そんなレベルを遥かに上回る。

(6)ゲームバランス

やりこみ要素が強いのに、廃人初心者も、小学生大きなお友達も、みんな楽しめる。

極めて凶悪なコンボがありながら、完璧なハメ手がない。


以上、近作のポケモンゲーム史上画期的というようなシステムはない。

ただ、集大成だ。

そのクォリティが高すぎて、RPGというよりもポケモンという新しいジャンルだと言っていい。

しかし、おそらくこんないろんな要素を絶妙なバランスで詰め込むのは他社には出来ない芸当だったと思う。

どうせ子供向けだろとか、グラフィックドットが粗いとか、そう思って見向きもしてないだろうけど、みんなポケモンやってみてくれ。

2010-04-21

保守世代での同人発行部数のススメ

ハナから売れてるような人でなく、少部数の小規模サークルへ向けて。

  

無謀にもネームバリューもなしに400部や500部を刷る勇気ある若者もいるこの時世。

廃棄される同人誌環境に悪いだろう、と思いそういったケースが起きないように

傾向と対策として、最低発行部数を見積もれる計算式を、ないなりの頭で考えてみた。

  

基本は数値を掛けていく。

  

まず第一に考えるのが画力。ここではABC3段階に分けよう。

次にイベント規模A,B,C(コミケ,コミックシティ,コミックトレジャー)、ネット認知度A,B,C(アクセス数=では安直?)

最後に、表紙、表紙の加工、ページ数、価格

  

第一項目では、画力A(巧い)B(普通)C(へたっぴ)、となる。ここの判断が明確ではないのでまぁ、自分で線引きを。

  

画力の基本値を1とし、A(4)B(3)C(1.5)とする。

次にイベントでの倍率を(Aコミケ等, 3),(Bサンクリ等, 2.5),(Cコミトレ等, 2)

ネット認知度、(Aわりと, 2),(Bそこそこ, 1.5),(C無名, -)

表紙は(A巧い, 1.5),(B無難, 1.25),(Cうーん?, -)となって、

加工の有無(オフPP 1.5),(オフPPなし, 1.25),(コピー紙, -)

ページ数(18P未満, -)(18P以上, 1.25)(30P以上, 1.5)

価格(500円以上, -),(400円, 1.5),(300円, 2),(200円, 2.5),(100円, 2.5),(無料, -)

  

さて、描き揃えた所で、仮に無名のへたっぴ同人作家コミケで出す場合計算してみよう。

  

■へたっぴ、コミケ、無名、コピー本、30P以上、200円で売る。

画力1.5 x コミケ3 x 無名- x 表紙1.25 x コピー紙- x ページ数1.5 x 価格2.5 = 21部 と大体20部。

  

次の例はネットごく一部で割りと認知されている人物、無論同人は初めて。

  

画力普通コミケ、わりと、巧い、PP、18P以上、価格500円とした。

画力3 x コミケ3 x わりと2 x 巧い1.5 x PP1.5 x 18P以上1.5 x 価格- = 60.75部 と少ないかも。初回という事もあるので無難か?

  

基本的にあまり多くの部数が出るようにはなっていない。MAXで200部くらい。最低で3部。

爆死回避の為に作った表みたいなもんで、実際の所は、運と直感、その他諸々で動く事だろうと。

  

  

価格帯での倍率は巧さに比例するだろとか、18P以上の倍率基準は

誰が決めたとか、合同本は?成年補正は?、売れなかったぞゴラァとかのつっこみはナシで…。

目安の最低を出す意味で、簡易すぎるがこんなの作ってみた次第。

  

保障はできないが、参考程度にはなるかな、という感じ。

もっと正確な項目と計算法でジェネレーターとかあったら面白い

  

…というか無難に50部刷れば安心だよって話でFAですかね。

追記:0に何を掛けても0だわな…小学生でもわかるのに。指摘ありがとう、感謝

2010-02-20

ttp://natalie.mu/music/pp/quruli/page/3

音楽芸術ではなくなったっていうことなんですかね。僕はすごい好きな指揮者がいて、その人が書いてる本の中で、けっこう目から鱗が落ちるようなことが書いてあったんですけど、産業革命以前のヨーロッパでは、ほんまに文化芸術っていうのがいろんな物事の中心、人の喜びの中心にあったんですけど、産業革命以降っていうのは、そんなことよりも新しい冷蔵庫を買うとか、そういうことのほうが人にとって価値のあることになって、音楽っていうのは趣味の1つに成り下がってしまったと。それを読んで「ああ、なるほどね」と思って。

2009-09-13

毎朝の推測と反駁

人間は手の抵抗と皮膚感覚を通じて推測した脳内自分の顔の形についての概形から適応的にカミソリに加える力のベクトルを制御する。曲面の形状の予測に失敗すると、カミソリの刃が肌に食い込むことになる。これはあなたのモデルが反証されたことを意味する。

電気カミソリを使う人は真理に興味がないのである。

Reference: Masuda A, Refutable theories of safe shaving, Journal of Theoretical Shavology, Vol. 18 (Evilseer, 2009), pp. 93-98

2009-08-30

インドの高校世界史教科書『世界史のテーマ』目次

http://anond.hatelabo.jp/20090829003621

序文


前書き



セクション1―草創期の社会

前書き

年表1(600万年前から前1世紀)

テーマ1―時のはじまりから

テーマ2―書くことと都市の生活



セクション2―帝国

前書き

年表2(前1世紀頃から1300年)

テーマ3―三大陸に亘る帝国

テーマ4―イスラームの中心地

テーマ5―遊牧民の帝国



セクション3―変わりゆく伝統

前書き

年表3(1300年頃から1700年)

テーマ6―三つの身分

テーマ7―変わりゆく文化伝統

テーマ8―文化の対峙



セクション4―近代化へ

前書き

年表4(1700年頃から2000年)

テーマ9―産業革命

テーマ10―先住民の排除

テーマ11―近代化への(複数の)道



結論

出典:National Council of Educational Research and Training, 2006, Textbook in History for Class XI: Themes in World History, New Delhi, pp. ix.

注1

テーマ内の見出し ( )内は訳者による補足

「テーマ1―時のはじまりから」

「人類の進化の話―a 現生人類の先行者たち」

「人類の進化の話―b 現生人類」

「初期人類―食料獲得の方法」

「初期人類―森から洞窟・原野へ」

「初期人類―道具の製作」

「コミュニケーションの形態―言語と芸術」

「アフリカにおける狩猟採集民との出会い」

「狩猟採集民の社会―現在から過去へ」



「テーマ2―書くことと都市の生活」 

「メソポタミアとその地理」

「都市性の意味」

「都市とモノの流通」

「文字の発達」

「記録の方法」

「リテラシー」

「文字の使用」

「南メソポタミアにおける都市化―神殿と王」

「都市の生活」

「牧畜地帯の中の交易都市」

「メソポタミア文化における都市」

「文字の遺産」



「テーマ3―三大陸に亘る帝国」(ローマ帝国史)

「初期の帝国」

「三世紀の危機」

「ジェンダー・リテラシー・文化」

「経済の拡大」

「働き手の統制」

「社会の階層」

「古代後期」



「テーマ4―イスラームの中心地」

「アラビア半島におけるイスラームの興隆―信仰・共同体・政治」

「カリフ―拡張・内戦・分派形成」

「ウマイヤ朝と政体の集権化」

「アッバース朝革命」

「カリフの凋落とスルタンの台頭」

「十字軍」

「経済―農業・都市化・商業」

「学問と文化」



「テーマ5―遊牧民の帝国」

「前書き」

「社会的・政治的背景」

「チンギス・ハーンの生涯」

「チンギス・ハーン後のモンゴル帝国」

「社会・政治・軍事組織」

「結論―世界史の中のチンギス・ハーンとモンゴル帝国」



「テーマ6―三つの身分」(西洋中世史)

「封建制とは」

「フランスとイングランド」

「三つの身分」

「第二身分―貴族」

「荘園」

「騎士」

「第一身分―聖職者」

「修道士」

「教会と社会」

「第三身分―農民、自由農民と農奴」

「イングランド」

「社会・経済関係に影響を与えた要因」

「環境」

「土地利用」

「新しい農業技術」

「第四身分?―新しい都市と都市民」

「大聖堂の都市」

「14世紀の危機」

「社会不安」

「政治の変化」



「テーマ7―変わりゆく文化伝統」(ルネサンス)

「イタリア都市の再興」

「大学と人文主義」

「人文主義者の歴史観」

「科学と哲学―アラブの貢献」

「芸術家とリアリズム」

「建築」

「初の活版印刷書」

「人間に対する新しい考え方」

「女性の志」

「キリスト教内部の論争」

「コペルニクス革命」

「世界について学問する」

「14世紀にヨーロッパ「ルネサンス」はあったか」



「テーマ8―文化の対峙」(南アメリカの文明と植民地化)

「カリブ海とブラジルの人々」

「中央・南アメリカの国家体制」

「アステカ帝国」

「マヤ文明」

「ペルーのインカ帝国」

「ヨーロッパ人による探検航海」

「大西洋を渡る」

「アメリカにおけるスペインの帝国樹立」

「コルテスとアステカ帝国」

「ピサロとインカ帝国」

「カブラルとブラジル」

「征服・植民地・奴隷貿易」



「テーマ9―産業革命」

「なぜイギリスか」

「都市・貿易・金融」

「石炭と鉄」

「綿紡と織布」

「蒸気力」

「運河と鉄道」

「変化した生活」

「労働者」

「女性・児童・工業化」

「抗議運動」

「法による改革」

「「産業革命」についての論争」



「テーマ10―先住民の排除」

「ヨーロッパの帝国主義」



「北アメリカ」

「先住民」

「ヨーロッパ人との出会い」

「相互の認識」

「土地を失った先住民」

「ゴールドラッシュと工業の成長」

「憲法で定められた権利」

「変化の風・・・・・・」



「オーストラリア」

「変化の風・・・・・・」



「テーマ11―近代化への(複数の)道」

「前書き」



「日本」

「政治体制」

「明治維新」

「経済の近代化」

「工場労働者」

「好戦的なナショナリズム」

「「西洋化」と「伝統」」

「日常生活」

「「近代の超克」」

「敗戦後―グローバルな経済大国としての再生」



「中国」

「共和国の樹立」

「中国共産党の台頭」

「新しい民主主義の確立―1949~65」

「国家像の対立―1965~78」

「1978年からの改革」

「台湾の話」

「近代化への二つの道」

2009-08-29

世界史を読むということ―インドの世界史教科書から

以下は、いわゆるインドの高校世界史教科書、『世界史のテーマ』前書きの試訳である。

       「世界史を読むということ」



                                       ニーラドリ・バッタチャールヤ(チーフ・アドバイザー)



 「どうしたら一年間で世界史を勉強することができるのでしょうか」とあなたはきくでしょう。「様々な国でとても沢山の出来事が起こり、それぞれの国でとても沢山のことが書かれてきました。その広大で限りないコーパスの中から、勉強すべきほんの少しのテーマをどうやって選べばよいのでしょうか」と。



 それはもっともな疑問です。どんな種類のものであれ、世界史の本を読む前には、そのような疑問に答える必要があります。シラバスというものは、どのように組み立てられているのか明らかにしなければなりません。本もその狙いを説明すべきでしょう。



 歴史を学び、書くという営みの中で、史学者は常に選択を必要とするということを忘れてはなりません。これは、素晴らしい小冊子『歴史とは何か』の中で、E・H・カーが何十年も前に指摘したことです。かび臭い文書館の膨大な史料の山を渉猟した後、史学者は重要と思われた事実を書きとめます。彼は、それらの事実を、その他の文書館で同様にして集めた証拠と付きあわせます。彼は読んだもの全てを写しとることはできませんし、集めた証拠を全て使うこともできません。ある史学者にとって意味を成さない証拠は、顧みられないまま残されます。時が経って、新しい疑問を抱いた史学者が同じ記録を読むことでしょう。彼女はそれまで見過ごされていた証拠を発見します。彼女はその証拠を解釈し、新たに既存のものと結びつけ、新しい歴史の本を書くでしょう。



 歴史を書く営みは、この選択という要素と切り離すことができません。ですから、歴史を読むときには、どのような出来事に史学者が焦点を合わせているのか、それらをどのように解釈しているのか、ということに注意を払う必要があります。私たちは、史学者が展開している大きな議論、特定の出来事に意味を持たせる大きな枠組みを理解する必要があるのです。



 最近まで、私たちが読む世界史というものは、しばしば近代西洋の興隆についての話でした。それは、切れ目のない進歩と発展の話でした(技術と科学、市場と貿易、理性と合理性、自由と解放の伸展)。ある出来事についての歴史は、この西洋の勝利という大きな物語の中で組み立てられることがとても多かったのです。帝国による世界の統制は、そのような過去の認識に基づいていました。西洋は、世界を文明化し、改革を導入し、土人を教育し、貿易と市場を拡大する、進歩の運び手と自任していました。



 今日、私たちはこのような認識に疑問を持つべきではないでしょうか。そのためには、世界史を見直す必要があります。いくつもの大陸と長い時間を渡り歩き、世界史を新しく捉えなおすことができるか調べてみなければなりません。『世界史のテーマ』はその旅路のお手伝いをします。



 それは、三つの方法によります。



 その一つ目として、発展と進歩という輝かしい物語の陰となっている暗い歴史を紹介します。15・16世紀の南アメリカへの冒険者と貿易商の到来は、西洋の商業と文化を単に押しひろげたわけではなりません。疫病を撒き散らし、文明を打ち壊し、人口を激減させたのです(テーマ8)。後年、白人の入植者が北アメリカとオーストラリアへ移住したときも、単なる進歩のみがあったわけではありません(テーマ10)。これらの地域における近代資本主義社会発展の歴史の背後には、原住民の排除、ジェノサイドとさえ言える不穏な話が横たわっているのです。



 二つ目として、国家と帝国の形成を扱う第二セクションがあります。そこでは、ヨーロッパのローマ(テーマ3)のみならず、イスラームの中心地の諸国家(テーマ4)、モンゴル人の国(テーマ5)についてのドラマが明らかにされます。これらの章では、それぞれの地域において、非常に異なった方式で社会と政体が構成されていたことが述べられます。



 三つ目として、第四セクションは様々な近代への道を叙述します。かつては、工業化というものはイギリスで初めて起こり、その他の国々は色々な方法でそれを模倣しようと努めたと信じられてきました。そのような議論では、西洋は再び世界の中心とみなされています。しかし、今日の私たちは、創造性の全てが西洋起源でないことを知っています。しかしながら、反対に、西洋は外の世界の歴史に何の影響力も持たなかった、とか、それぞれの国の発展は独立に起こった、とか、発展の自生的な起源のみに注目すべきだ、などと単純に主張することもできません。それはとても視野の狭い見方であり、地方根性の一種です。そのかわりに、それぞれの国の人々がそれぞれ創造性を発揮して生活世界を形作り、それらの発展が、ヨーロッパを含めた他の国々や大陸に対し、交互に影響を与えたことを理解する必要があります。テーマ7では、ルネサンス期のヨーロッパが、外の世界の発展から多大な影響を受けたことを知るでしょう。



 あなたの旅は、人類社会の始まり(テーマ1)と都市の始まり(テーマ2)から始まります。次に、三つの別々の地域で、巨大な国や帝国がどのように発展したのか、それらの社会がどのように成り立っていたのかを知るでしょう(セクション2)。続くセクションでは、9世紀から15世紀にかけて、どのようにヨーロッパの文化と社会が変化したか、そして、ヨーロッパの拡大が南アメリカの人々にとって何を意味したのかを詳しく知るでしょう(セクション3)。最後に、近代世界の形成に関わる複雑な歴史について知るでしょう(セクション4)。それぞれのテーマの多くは、その分野で交わされている論争について紹介し、史学者が途切れることなく古い問題を新しく捉えなおしていることを示すでしょう。



 どのセクションにも、前書きと年表があります。それらの年表は試験に備えて暗記するためのものではありません。それらは、ある時期に世界の色々な場所で何が起こっていたのか考えるきっかけを作るためにあるのです。それは、ある場所の歴史を別の場所のそれと関連づける手助けとなるでしょう。



 年表を作るということは常に困難を伴います。どのように焦点を合わせるべき日付を選べばよいのでしょう。全ての史学者が賛成することはないでしょう。事実、同じ時代について、色々な本で掲げられている年表を見比べてみれば、強調されている論点が異なることに気づくことでしょう。ですから、それが何を伝え、何を伝えていないのか、それぞれの年表を批判的に読む必要があります。年表は独自の方法で歴史を構成するのです。



 今年度、あなたが南アジアの歴史を勉強することはありません。来年度、あなたは『インド史のテーマ』を読むことになります。この二年間(第11学年と12学年)で、世界史上の重要な出来事と歴史過程のいくつかについて理解するだけではなく、どのように史学者が過去を知るようになったかわかるようになるでしょう。彼らの用いる史料について、それらへの焦点の合わせ方について、歴史的知識というものが、解釈の繰り返しと論争を通して発展してきたことについて、知ることになるでしょう。

出典:National Council of Educational Research and Training, 2006, Textbook in History for Class XI: Themes in World History, New Delhi, pp. v – vi.

2009-07-25

女性差別(笑)

http://www.asahi.com/international/update/0724/TKY200907240216.html

まあ、女性差別はなくさにゃならんよーという所に同意はするけどさ、こういうニュースがあがってくると「だから日本ダメなんだ!」と喜色満面にブコメしてる連中キモいキモい事(笑)。ほんと「国家」とか「政府」とか巨大な存在を批判したつもりになってストレス発散するの好きだよなあいつら。

この「女性差別撤廃委員会」の委員の一覧はこれな。

http://www.un.org/womenwatch/daw/cedaw/members.htm

Ms.Ferdous Ara Begum バングラデシュ
Ms.Magalys Arocha Dominguez キューバ
Ms.Meriem Belmihoub-Zerdani アルジェリア
Ms.Saisuree Chutikul タイ
Ms.Dorcas Coker-Appiah ガーナ
Ms.Mary Shanthi Dairiam(Rapporteur) マレーシア
Mr.Cornelis Flinterman オランダ
Ms.Naela Mohamed Gabr (Vice-Chairperson) エジプト
Ms.Françoise Gaspard (Vice-Chairperson) フランス
Ms.Ruth Halperin-Kaddari イスラエル
Ms.Tiziana Maiolo イタリア
Ms.Violeta Neubauer スロベニア
Ms.Pramila Patten モーリシャス
Ms.Silvia Pimentel ブラジル
Ms.Fumiko Saiga 日本
Ms.Hanna Beate Schöpp-Schilling ドイツ
Ms.Heisoo Shin 韓国
Ms.Glenda P. Simms (Vice-Chairperson) ジャマイカ
Ms.Dubravka Šimonović (Chairperson) クロアチア
Ms.Anamah Tan シンガポール
Ms.Maria Regina Tavares da Silva ポルトガル
Ms.Zou Xiaoqiao 中国

こういう組織でも国ごとの政治力とかがもろに影響出るわけ。

たとえばこの委員会中国に対して上記記事のように何か苦言を呈した事は殆どございません(笑)。状況を報告してくるNGOとか団体が全部共産党の子飼いってのもあるけどな。フランスがそれを突っ込んだ事あるけどシカトされてるし。

他の国も似たような事言われたら「ハァ何言ってんの?俺んとこはちゃんとやってますが何か?」と突っぱねてるケースが大半、というか通例になってる。そういう組織なわけ。当たり前だけど、日本も同じようにスルーするだろうね。

2009-04-28

ポケモンプラチナ、バトルファクトリーで最近あったこと

2009-04-22

http://anond.hatelabo.jp/20090420220613

conservativeでないGCの方が古くからあったのだから、conservative GCのconservativeを「古くさい」と取るのはおかしいでしょう。

最初に使ったのが誰かということについてだが、現在言うところのConservative GC = conservative pointer findingを行うGC、という用法を導入したのは Boehm and Weiser, Garbage Collection in an Uncooperative Environment, Software Practice and Experience 18(9) pp.807--820, 1998. だと思う。

元増田の主張についてはもっともだと思うな。「保守的GC」というのを見ると頭の中で「conservative GC」に置き換えてたので気にならなかったけど。

2009-04-03

毛について

人間、誰しも毛が生えている。

男も女も元男も元女もみんな生えている。男と元男にしか生えない毛は一本だけ。

毛の濃い人はとにかく濃い。女にもいるが男に多い。陰毛は機動性に優れている。

ところで、毛を抜いたらどうなるのだろうか。

・毛根を刺激し、太い毛が生えてくる。

だんだんと薄くなる。

という真逆の二説がある。真実は一体どっちなのか。

僕のおっかぁが太くなる派なのでそれが正解なのは間違いないのですが、一応確証は欲しい。

ですが調べるのが面倒。なら自分の体で試そう。

ここまでは2年くらい前の話でありましてつまり僕は、ここ2年間、頑張ってスネ毛を抜き続けました。

ピンセットによるよる手作業。そろそろ毛抜き職人の域に達したと思います。

そして1か月ほど抜かずに放置をしました。果たして結果はどうなるのか。

僕の大学受験を捨てた科学的調査の結果はどうなるのか。

毛にかけた高校二年間、あと一年で取り返せるのか。

なんか面倒なので結論だけ言います。

一部ですが、毛が生えなくなりました。

1か月経っても生えてこないので、毛根から死滅していると思われます。

あ、未だに生え続けている毛の濃さは全く変わっていません。

埋没毛を無理矢理ほじくり返して抜いたせいでボロボロだった皮膚も、1か月の内に復活しました。

さあ、ここに新事実が生まれました。

毛は抜き続けると生えなくなる。

これによって自動的にハゲの原理も解明できました。

人間の毛(もちろん髪も)は毎日毎日、生えては抜け生えては抜けを繰り返しています。

そして、一毛穴が生やすことのできる本数は(個体差はあれど)決まっていると思われます。

年を重ねるにつれ一毛穴の限界発毛数に近づきます。そしてついにリミットブレイクを起こした毛穴が、ハゲとなるのです。

リーブ●1は人型対G兵器和田○子が喝ッ! を入れることで限界発毛数を強制的に増やすのでしょう。PPマックスみたいなもの。

2009-03-21

来客とその場で楽しめるゲームソフトをあまり持っていない事に気付く

今まさにそういう必要に迫られてる状況に陥っているわけだ。

大まかなゲームソフト所有リスト

PS2
PS3

どれもこれも料理にたとえるなら高タンパクカロリーで脂っこいものばかり。

  • 性別・年齢層を問わないゲーム内容
  • プレイ時間はせいぜい半日程度
  • すぐに操作方法を習得出来る
  • やめるときにはすっぱりやめられる
  • 熟練者(つまり俺)と対戦可能。しかもそれなりにいい勝負が出来る

上記のような条件に当てはまるソフトとなると、何があるかな…。

2009-01-26

http://anond.hatelabo.jp/20090126174521

増田だが、「累犯障害者」の第3章を読んでみることをオススメする。

I'm Yoko-Masuda. I recommend for you to read Ch.3 of "Ruihan Syougai-sha" written by J. Yamamoto.

累犯障害者 獄の中の不条理(単行本) 山本譲司 (著)

http://www.amazon.co.jp/dp/4103029315/

第3章(pp.105-123) 生きがいはセックス売春する知的障害女性たち

2008-12-01

まあ、東浩紀も一応予防線は張っていて

10万はてなポイントを進呈します。東浩紀歴史修正主義を基礎づける記述が<デリダの文献にある>ことを発見できたら

http://d.hatena.ne.jp/toled/20081128/p1

進化論否定論者のように南京虐殺を扱う東浩紀

http://d.hatena.ne.jp/tikani_nemuru_M/20081130/1228056396

さすがにこれについては本人、この対談の中でもう少し触れています。

リアルのゆくえ』pp.220 - 221

東 (前略)個人の価値観でこういう風に生きてもらいたいとか、こういうふうに生きるべきだということを、友人や知人に言うことと、社会のみんながそれを信じるかどうかということについての予測は、まったく関係がないでしょう。その時に、ぼくは、そういう友人や知人を増やしていきたいとは思う。それこそが希望だから。でもそれは社会への絶望と両立するしかないんですよ。


大塚 それが公共性っていうことなんじゃないの?


東 それを公共性だというのであれば、南京虐殺は絶対になかった、韓国人中国人はいますぐ死ぬべしと友人や知人に向けて書いている連中と同じになる。だって、彼らもそれは公共的な言説だと信じているのだから。だから私的な希望と公共性を混同することはできない。


大塚 (中略)たしかに、ネット人間たちの狭い議論の中で、南京虐殺はなかったという人間と、あったという人間の間に何かが生まれると思うのは不毛なのかもしれないけど、ぼくはそこに、何かが生まれないとはやっぱり思わないし。


東 たとえ生まれたとしても、それは関係がない。問題はそんなことではなくて、ぼくが言いたいのは、いまやいろんな人間自分思想こそが公共的だと勘違いして、何億というホームページを開設して情報を垂れ流している。その時に、それに対して、ぼくこそが公共的なのだ、なぜならぼくは本も出しているし、東大とかも出てるからと言うわけにはいかないでしょう、ということです。もしそんな立場をとったら、それこそ不遜というものですよ。


大塚 ぼくの言っている公的というのはそうじゃない。あなたがいう公的というのは、俺のことを認めろ、ということだってのがよく分かったんで、理解はするけれども、ぼくはそういう意味では公的っていう言葉をまったく使っていない。ぼくは、つねに他者との関係によってあらわれるものを公的と言っているわけだから。


東 そんな公共性はネットによって実現されている。そのうえで、その「公共性」がいったい何を生み出しているだろうかというのが、先ほどから言ってるぼくの失望です。

同 pp.222-223

東 今なら、南京虐殺について調べたいと思ったら、ネット上で、一瞬にして、いろんな立場の人の意見を読むことができる。だから、その意味では、大塚さんのいう「公共性」は実現している。で、読んだから何が起きているのか、っていう話です。読んだから、そこで議論ができる。本当に真実の議論ができるか、それはできない。なぜかといったら、真実になんて誰にも近づけないからです。そうするとそこで起こるのは、誰が優位に立てるかの競争だけです。(中略)情報量が大きくなると「誰が頭がいいか競争」しかできなくなってしまう。


大塚 それは情報量が大きくなったからじゃなくて、まだそこに生きるわれわれがそういった環境に対して、どのように情報の処理や判断をしていくかの訓練ができていないからだと思うけど。


東 ぼくは、リテラシーの発想では対応は無理だと思います。


大塚 少なくともリテラシーの問題として対応し得る部分が、ぼくには充分ありうると思うけど。


東 リテラシー論というのは、普通読者の側の論理ですね。つまり読む側の話です。


大塚 いや、リテラシー論っていうのは、発信者論でもあるんだよ。読者の論理ではなく、書き手を教育する論理だと思う。


東 (略)百歩譲って、受信者リテラシー教育可能かもしれない。(中略)しかし、発信者能力教育するというのは難しい。人びとがネットで好き勝手なことを流す権利は、教育では止められない。だって、彼らはそれをやりたいんだから。


大塚 いや、発信者教育はできる。にもかかわらず発信者としてあるための教育が未だなされていないということが問題だと思う。(中略)だからぼくはインターネットによって書く主体や、書き手としての自分、発信者としての自分というものを、この国において全員が意図すれば獲得できるという環境が生まれたときに、少なくともそれを断念していいほどに近代を通じてまだ努力はされていないと考える。(後略)



d:id:tikani_nemuru_Mさんは、

無限に開かれた討議」というのは、根拠とか証拠とかデータを参照せずに、ひたすら思いこみだけでしゃべることも認めなくてはならにゃーようですにゃ

と東を批判します。この批判は全く妥当だと私も思います。少なくとも、知識人という立場にあるものが、知や学問に対してこのように不誠実であってはならない。大塚はこの対談では一貫してそういう立場から、東への激しい苛立ちを隠さずぶつけ続けていきます。


しかし一方で、おそらく東はそんな批判は織り込み済みなのだろうとも思います。たとえば、上記のような批判に対しては、それでは「ひたすら思い込みでしゃべる」人間を公共圏から駆逐していいのか、それが「公共圏」なのか?という反論も可能でしょう。そこまで下品な反論でなくとも、フレイザーは「複数のマイノリティによる多元的公共圏」は、それらの中には決して上品でないものも含まれうるが、しかしそれでも単一の公共圏よりはいいのだ、ということを「公共圏の再考:既存の民主主義の批判のために」で書いていたように記憶しています。

(もちろんフレイザーは、歴史修正主義公共圏?を容認はしないでしょうけれど)

さらに言うならば、インターネットの時代において、「ひたすら思い込みでしゃべる」人間を駆逐することがそもそも可能なのか、また、彼らが公共圏の議論に参加可能なレベルの「知の技法」を身につけることが可能なのか?という問いもあるでしょう。そして、東はその可能性に完全に絶望しています。ゆえに、

(同、p.189)

公民的な自覚をもたない人をどれだけ抱えられるか、そちらから社会設計を考えるしかない。これがぼくの前提です。


(同、p.231)

市民であり公民であることが正しい人間であり、それを育てていくことでしか社会は変えられないという理念に対して、ぼくは違和感がある。ぼくの関心は、むしろ、全員を市民公民に育てあげることなど不可能だという諦めのうえで、でもそれでもいい社会をつくるにはどうするか、というところにある。

と語ります。


つまるところ、東が歴史修正主義を「容認」するとすればその限りにおいてであって、歴史修正主義者がどれほどネットの中で暴れ回ろうとも、結果として歴史修正が実現しないような社会であればそれでいいし、それよりない、と言っているように私は読みます。その結果として歴史修正主義を容認したように見えたとしても、それはそうした態度の反射的効果にすぎない、とは言いうるかもしれない。


とするならば、デリダ歴史修正主義を支持もしくは黙認した言葉が彼の著書にあるか、と聞くよりは、デリダ思想が、公共圏に対する東の絶望に結び付くのか否かを問うた方が生産的であるように思います。おそらく東本人も、デリダ歴史修正主義についてどう語ったかは問題ではないと語るでしょう。もちろんそこは、十分に問題ではあるのですが、そこで水掛け論を行っても仕方がない。

大塚―東対談における大塚は、激しい苛立ちと同時に、東から一生懸命言葉を引き出そうと我慢を重ねています。もちろん大塚の我慢を我々が共有する必要は微塵もありませんが、しかし東の公共性に対する批判を行うとき、どれだけ絶望しようと対話の中から公共性を見出していこうとする大塚の態度に私は共感を覚えるし、それに倣うべきだという態度を取りたいという志向は否めません。

2008-10-19

YourFileHostの動画をなんとかする

YourFileHostのCAPTCHA画像をなんとかするの続きの続き。

まぁ、なんというか、一応できたので張ってみる。微妙な出来栄えだけど。

decaptcha.rbと同じディレクトリに置いて適当に動かしてみてください。

どっかにいいRSSがないかなぁ。。。

しかし、CAPTCHA画像を相手にしてた時の方が楽しかったなぁ。。。

あと、添削とかいろいろ歓迎です。

追記

なぜか&が&に置き換えられてるみたいなので、適当に&に読み替えてください。

download.rb

#!/usr/local/bin/ruby
$LOAD_PATH << File::dirname(File::expand_path($0))
require 'rubygems'
require 'rss'
require 'mechanize'
require 'decaptcha'
# require 'ruby-debug'
# require 'pp'

DESTDIR = 'files'
TMPDIR = '/tmp'

class Downloader
  COOKIE_URI = 'http://www.yourfilehost.com/media.php?cat=video&amp;file=%s'
  DOWNLOAD_URI =
    'http://www.yourfilehost.com/downloadlink.php?cat=video&amp;file=%s&amp;adult=1'
  VERBOSE = false
  DEBUG = false
  
  def self.fetch(file, destdir)
    puts "Fetching file: #{file}"

    destfile = destdir + '/' + file
    if test(?e, destfile) then
      puts '  - Already exists. skip'
      puts
      return nil
    end
  
    #
    # Initialize Mech
    #
    mech = WWW::Mechanize.new
    mech.user_agent_alias = 'Windows IE 6'
    mech.max_history = 3
    mech.open_timeout = 15
    mech.read_timeout = 3
  
    #
    # get cookie
    #
    uri = COOKIE_URI % file
    page = mech.get(uri)
  
    #
    # Challenge against CAPTCHA
    #
    uri = DOWNLOAD_URI % file
    page = mech.get(uri)
  
    for i in 0...3
      captcha_path = (page/'img[@height="38"]').attr(:src)
      captcha_uri = 'http://www.yourfilehost.com/%s' % captcha_path
      gif = mech.get_file(captcha_uri)
      open("#{TMPDIR}/captcha.gif", 'w') {|fd| fd.write(gif) }
      mech.back
  
      code = DeCAPTCHA.decode("#{TMPDIR}/captcha.gif")
      File.unlink("#{TMPDIR}/captcha.gif")
      if code.nil? then
        puts '  - CAPTCHA decode failed. retry' if VERBOSE
        next
      end
  
      form = mech.page.forms.first
      form.verify = code
      page = mech.submit(form)
  
      break unless page.links.empty?
    end
  
    if page.links.empty? then
      puts '  - Failed 3 times.  Try another one.'
      puts
      return nil
    end
  
    #
    # download
    #
    puts "  - Downloading: #{page.links.first.href}" if DEBUG
    retry_count = 0
    video = nil
    begin
      video = page.links.first.click
    rescue Timeout::Error => evar
      retry_count += 1
      if retry_count < 5 then
        puts "  * Timedout, retry" if VERBOSE
        retry
      end
      raise evar
    end

    unless video.instance_of?(WWW::Mechanize::File) then
      if DEBUG then
        puts "  - Something wrong while downloading. skip."
        puts
      end
      return nil
    end
    video.save(destfile)

    return destfile
  end
end



#
# main
#
[DESTDIR, TMPDIR].each do |dir|
  if !test(?d, dir) or !test(?w, dir) then
    puts "#{dir}: Directory not exists or cannot write."
    exit
  end
end

files = []


# collect URIs from RSS
RSS_URI = [
  ['http://www.yourfilehost.com/make-rss.php?range=day&amp;af=off',
    lambda {|rss| rss.items.map {|x| x.link }},
  ],
]
RSS_URI.each do |uri, preprocessor|
  rss = RSS::Parser.parse(uri)
  uris = preprocessor.call(rss) #=> Array of URI of YourFileHost

  uris.map {|x| /file=([^&amp;]*)/.match(x).to_a[1] }.each do |file|
    # next if file !~ /\.wmv/  # uncomment it if you need only wmv
    files << file
  end
end
files.uniq!


# download
files.each do |file|
  begin
    Downloader.fetch(file, DESTDIR)
  rescue SystemCallError, Timeout::Error => evar
    puts "  - error (#{evar.to_s}). skip."
    puts
  end
end
__END__

2008-10-18

http://anond.hatelabo.jp/20081018072817 の続きだよ

これでおしまいだよ

elisp

sangels.el
(require 'cl)				; for cl-seq

(defvar sangels-movies-dir nil)
(defvar sangels-player "c:/Program Files/GRETECH/GomPlayer/GOM.exe")
(defvar sangels-sort-by 'sangels-sort-by-rate)
(defvar sangels-rate-file "~/.emacs.d/.sangels/rate")
(defvar sangels-buffer "*sangels*")
(defvar sangels-thumbnail "00_thumbnail.jpg")
(defvar sangels-m3u "00_movies.m3u")
(defface sangels-name '((t (:family "fixed" :weight bold :height 3.0)))
  "")
(defface sangels-rate '((t (:family "fixed" :weight bold :height 1.5)))
  "")
(defvar sangels-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map "n" 'next-line)
    (define-key map "p" 'previous-line)
    (define-key map (kbd "RET") 'sangels-select)
    (define-key map (kbd "SPC") 'sangels-select)
    (define-key map "q" 'sangels-quit)
    (define-key map "+" 'sangels-rate-plus)
    (define-key map "-" 'sangels-rate-minus)
    map))
(defvar sangels-mode-hook nil)
(defvar sangels-highlight-overlay nil)
(defvar sangels-rate-alist nil)

(defconst sangels-rate-max 6)

(defun sangels-insert-movies ()
  (save-excursion
    (let* ((inhibit-read-only t)
           (files (remove-if-not
                   (lambda (x)
                     (and (not (member (file-name-nondirectory x) '("." "..")))
                          (file-directory-p x)
                          (member sangels-thumbnail (directory-files x))))
                   (directory-files sangels-movies-dir t)))
           (ids (mapcar 'file-name-nondirectory files)))
      (erase-buffer)
      (setq ids (sangels-sort-ids ids))
      (dolist (id ids)
        (let ((file (expand-file-name id sangels-movies-dir))
              (pos (point)))
          (insert-image-file (expand-file-name sangels-thumbnail file))
          (end-of-line)
          (insert (propertize (format "%-15s " id)
                              'face 'sangels-name))
          (sangels-insert-rate id)
          (insert "\n")
          (put-text-property pos (point) 'sangels-id id))))))

(defun sangels-sort-by-name (a b)
  (string< a b))

(defun sangels-sort-by-rate (a b)
  (or (> (sangels-rate a) (sangels-rate b))
      (sangels-sort-by-name a b)))

(defun sangels-sort-ids (ids)
  (sort ids
        (or sangels-sort-by
            'sangels-sort-by-name)))
(defun sangels-insert-rate (id)
  (let ((rate (sangels-rate id)))
    (insert (propertize (concat
                         (make-string rate ?★)
                         (make-string (- sangels-rate-max rate) ?☆))
                        'sangels-rate t
                        'face 'sangels-rate))))

(defun sangels-current-id ()
  (get-text-property (point) 'sangels-id))

(defun sangels-play-movie (movie)
  (let ((explicit-shell-file-name "cmdproxy")
        (shell-file-name "cmdproxy"))
    (apply
     'call-process-shell-command
     "start" nil "*tmp*" nil
     (mapcar (lambda (x) (concat "\"" x "\""))
             (list sangels-player
                   (unix-to-dos-filename movie))))))

(defun sangels-select ()
  (interactive)
  (let ((id (sangels-current-id)))
    (when id
      (sangels-play-movie (expand-file-name
                           sangels-m3u
                           (expand-file-name id sangels-movies-dir))))))

(defun sangels-quit ()
  (interactive)
  (kill-buffer sangels-buffer))

(defun sangels-rate (id)
  (or (cdr (assoc id sangels-rate-alist)) (/ sangels-rate-max 2)))

(defun sangels-rate-save ()
  (interactive)
  (let ((dir (file-name-directory sangels-rate-file)))
    (unless (file-exists-p dir)
      (make-directory dir t)))
  (with-temp-file sangels-rate-file
    (insert (pp-to-string sangels-rate-alist))))

(defun sangels-rate-load ()
  (interactive)
  (when (file-exists-p sangels-rate-file)
    (with-temp-buffer
      (insert-file-contents sangels-rate-file)
      (goto-char (point-min))
      (setq sangels-rate-alist (read (current-buffer))))))

(defun sangels-rate-plus (&amp;optional n)
  (interactive "p")
  (setq n (or n 1))
  (let* ((id (sangels-current-id))
         (cell (assoc id sangels-rate-alist)))
    (unless cell
      (setq cell (cons id (sangels-rate id)))
      (setq sangels-rate-alist (cons cell sangels-rate-alist)))
    (setcdr cell (+ (cdr cell) n))
    (save-excursion
      (let ((inhibit-read-only t))
        (beginning-of-line)
        (goto-char (next-single-property-change (point) 'sangels-rate))
        (delete-region (point)
                       (next-single-property-change (point) 'sangels-rate))
        (sangels-insert-rate id)))
    (sangels-rate-save)))

(defun sangels-rate-minus (&amp;optional n)
  (interactive "p")
  (setq n (or n -1))
  (sangels-rate-plus (- n)))

(defun sangels-post-command-hook ()
  (save-excursion
    (move-overlay
     sangels-highlight-overlay
     (progn
       (move-beginning-of-line 1)
       (point))
     (progn
       (move-end-of-line 1)
       (forward-line)
       (point))
     (current-buffer))))

(defun sangels-mode ()
  (interactive)
  (kill-all-local-variables)
  (use-local-map sangels-mode-map)
  (setq sangels-highlight-overlay (make-overlay 0 0))
  (overlay-put sangels-highlight-overlay 'face 'highlight)
  (overlay-put sangels-highlight-overlay 'evaporate t)
  (make-local-variable 'post-command-hook)
  (add-hook 'post-command-hook 'sangels-post-command-hook nil t)
  (setq major-mode 'sangels-mode)
  (setq mode-name "Sangels")
  (run-mode-hooks 'sangels-mode-hook)
  (set-buffer-modified-p nil)
  (setq buffer-read-only t))

(defun sangels (&amp;optional arg)
  (interactive "P")
  (when (or arg (not sangels-movies-dir))
    (setq sangels-movies-dir (read-directory-name "movies dir: ")))
  (sangels-rate-load)
  (switch-to-buffer (get-buffer-create sangels-buffer))
  (sangels-insert-movies)
  (sangels-mode))

(provide 'sangels)

2008-10-17

http://anond.hatelabo.jp/20081006220009

YourFileHostのCAPTCHA画像をなんとかするの続き。

その後、適当にいじったら、手元環境で1枚あたり25秒くらい→だいたい2.5秒くらいで判別できるようになった。このくらいなら使えるかな。

速度向上に一番効いたのは、Token#importで画像を比較しているところの修正。他は細かい手直し。

使い方は前のやつと変わってません。

あと、テストに100枚くらいCAPTCHA画像食わせてみたけど、とりあえず全部正しく判定できた。

動作確認用のスクリプト (run.rb)

カレントディレクトリ以下にある*.gifCAPTCHA画像ファイル適当に判別するスクリプト。動作確認用にどうぞ。

後述のdecaptcha.rbと同じディレクトリ適当に置いてchmod +xしてね。

#!/usr/local/bin/ruby
$LOAD_PATH << File::dirname(File::expand_path($0))
require 'decaptcha'

STDOUT.sync = true

Dir.glob('*.gif').sort.each do |file|
  correct = File::basename(file, '.*')
  puts "Processing file: #{file}"
  start_time = Time.now
  ret = DeCAPTCHA.decode(file)
  elapsed = Time.now - start_time

  puts "  Result: #{ret} (=> #{(correct == ret) ? "Ok" : "Fail"})"
  puts "  Elapsed time: #{elapsed}"
  puts
end

コード (decaptcha.rb)

#!/usr/local/bin/ruby
require 'rubygems'
require 'gd2'
require 'pp'

#
#= CAPTCHA画像解析モジュール
# CAPTCHA画像ファイルを食わすとあら不思議Stringが出てくるよ。
# YourFileHostのやつに対応。
#
#== Usage
# decoded_str = DeCAPTCHA.decode("some_captcha_image.gif")  #=> String
# 失敗したらnilが返る。
#
module DeCAPTCHA
  DEBUG = false

  #=== CAPTCHA画像デコード
  # file::    画像ファイル名のパス
  # method::  未指定でよい。男は細かい事を気にするな。
  # returns:: CAPTCHA画像解析結果(String) or nil (デコード失敗時)
  def self.decode(file, method = DeCAPTCHA::Site::YourFileHost)
    return method.new(file).decode
  end



  #= CAPTCHA画像デコードクラス
  # このクラスサブクラスはimport, tokenize, stream_parseメソッドの
  # 実装を含む必要がある。
  class Site
    def initialize(file = nil)
      @pix = nil
      self.import(file) unless file.nil?
    end
    def decode
      return stream_parse(tokenize())
    end
  end

  #= YourFileHostのCAPTCHA画像を解析するクラス
  class Site::YourFileHost < Site
    def import(file)
      @pix = PixelMatrix.new.import(file)
      return self
    end

    # importしたイメージ(PixelMatrix)から、文字と思わしきパターンを
    # 抽出して上下マージンを切り取ってArrayにして返す。
    # returns:: Array of PixelMatrix
    def tokenize
      ret = []
      state = :initial
      for x in 0...@pix.width
        case state
        when :initial
          if !@pix.vline_blank?(x) then
            state = :tokenize
            pixel = PixelMatrix.new(0, 0, true)
            ret << pixel
            redo
          end
        when :tokenize
          if @pix.vline_blank?(x) then
            state = :initial
            next
          end
          x0 = pixel.width
          for y in 0...@pix.height
            pixel[x0, y] = @pix[x, y]
          end
        else
          raise 'NOTREACHED'
        end
      end

      ret.map! {|token| Token.new.import(token.cutoff_vmargin!) }
    end


    # PixelMatrixのArrayを受け取り、数字を判別。
    # tokens:: Array of PixelMatrix
    # returns:: String (判別結果)
    def stream_parse(tokens)
      rs = tokens.map {|x| x.guess.to_s }.join('')
      if rs.length != 4 then
        rs = nil
        if DEBUG then
          puts '- guess failed. dumping guess result of each token:'
          tokens.each_index do |i|
            print "##{i}:#{tokens[i].guess} "
            pp tokens[i].candidate
          end
          puts
        end
      end
      return rs
    end

    class Token
      @@digits = nil
      attr_accessor :candidate

      def initialize
        if @@digits.nil? then
          # 文字画像サンプルを作っておく
          @@digits = DIGITS_ASSOC.map {|digit|
            PixelMatrix.new(0, 0, true).import_array(digit) }
        end

        @candidate = Hash.new
      end

      # PixelMatrixを受け取り、文字画像サンプルと比較して
      # 一致率を計算しておく。
      # pixel:: PixelMatrix
      # returns:: self
      def import(pixel)
        @@digits.each_index do |i|
          digit = @@digits[i]

          if (digit.width - pixel.width).abs   > 4 or
             (digit.height - pixel.height).abs > 4 then
            @candidate[i] = -1  # サイズが違いすぎな場合、一致させない
            next
          end

          correct_bits = 0
          enlarged_width  = [digit.width,  pixel.width ].max
          enlarged_height = [digit.height, pixel.height].max
          for y in 0...enlarged_height
            dy = (y.to_f / digit.height * enlarged_height).to_i
            py = (y.to_f / pixel.height * enlarged_height).to_i
            for x in 0...enlarged_width
              dx = (x.to_f / digit.width * enlarged_width).to_i
              px = (x.to_f / pixel.width * enlarged_width).to_i
              correct_bits += 1 if digit[dx, dy] == pixel[px, py]
            end
          end

          @candidate[i] = correct_bits * 100 /
                          (enlarged_width * enlarged_height)
        end

        return self
      end

      # importのときの比較結果をもとに文字を推測
      # returns:: Fixnum or nil(失敗時)
      def guess
        digit, ratio = @candidate.sort {|a, b| a.last <=> b.last}.last
        digit = nil if ratio < 0 or ratio < 65
        return digit
      end
    end
  end


  #= 画素マトリックスクラス
  # 画像ファイルを食わせると、各ピクセル(画素)を2値(black(1) or white(0))に
  # 変換して、内部で保持する。
  # 以後、Matrixクラスのような感じで個々の画素アクセスできる。
  class PixelMatrix
    BLACK = 1
    WHITE = 0

    attr_accessor :width
    attr_accessor :height

    # width::  幅
    # height:: 高さ
    # is_flexible:: 自動的に伸張するか
    def initialize(width = 0, height = 0, is_flexible = false)
      @matrix = Hash.new {|hash, key| hash[key] = Hash.new(WHITE)}
      @width, @height, @flexible = width, height, is_flexible
    end

    # file:: 画像ファイル名のパス
    # brightness_threshold:: 画素を黒とみなす閾値 (0 - 255, default: 0x40)
    # returns:: self (DeCAPTCHA::PixelMatrix)
    def import(file, brightness_threshold = 0x40)
      gd = GD2::Image.import(file)
      @width, @height = gd.width, gd.height

      self.each_with_axis do |x, y|
        color = gd[x, y]
        greyscale = (color.red + color.green + color.blue) / 3
        self[x, y] = (greyscale > brightness_threshold) ?
          WHITE :
          BLACK
      end
      return self
    end

    def import_array(array)
      array.each_with_index do |str, y|
        str.split('').each_with_index do |c, x|
          self[x, y] = c.to_i
        end
      end
      return self
    end

    # PixelMatrixを画像ファイルとしてexport
    # file:: 新たに作る画像ファイル名のパス
    def export(file)
      gd = GD2::Image::IndexedColor.new(@width, @height)
      gd.palette << GD2::Color::WHITE
      gd.palette << GD2::Color::BLACK
      self.each_with_axis do |x, y|
        gd[x, y] = {
          WHITE => GD2::Color::WHITE,
          BLACK => GD2::Color::BLACK,
        }[self[x, y]]
      end
      gd.export(file)
      return self
    end

    # 指定された位置の画素を返す。
    # returns:: PixelMatrix::BLACK(1) or WHITE(0)
    def [](x, y)
      if !@flexible and !in_range?(x, y) then
        raise RangeError
      end
      return WHITE if !@matrix.has_key?(y)  # XXX: for optimize
      return @matrix[y][x]
    end

    # 画素に値を設定。
    # returns:: PixelMatrix::BLACK(1) or WHITE(0)
    def []=(x, y, val)
      unless in_range?(x, y) then
        raise RangeError unless @flexible
        @width  = (x >= @width)  ? x + 1 : @width
        @height = (y >= @height) ? y + 1 : @height
      end

      @matrix[y][x] = val
    end

    def in_range?(x, y)
      ((0...@width) === x and (0...@height) === y)
    end

    # 指定された軸をもとに画素を走査し、Arrayに変換。
    # 例えば、to_a(:vertical, 10) とすると、x == 10 な列を取り出して
    # Arrayにして返す。
    #
    # axis:: 軸を指定 (:vertical または :horizontal)
    # pos:: 位置を指定。_axis_で指定した軸と直交する軸における位置を指定。
    def to_a(axis, pos)
      {:vertical => lambda {
        (0...@height).map {|y| self[pos, y]}
       },
       :horizontal => lambda {
        (0...@width).map  {|x| self[x, pos]}
       },
      }[axis].call
    end

    # returns:: Array
    def hline(y)
      self.to_a(:horizontal, y)
    end

    # returns:: Array
    def vline(x)
      self.to_a(:vertical, x)
    end

    # X軸方向に画素を走査。
    # y:: どの位置で走査するか
    # returns:: 指定された軸の上にドットが存在: false, 無い: true
    def hline_blank?(y)
      return true if @matrix.has_key?(y) == false # XXX: for optimize
      for x in 0...@width
        return false if self[x, y] == BLACK
      end
      return true
    end

    # Y軸方向に画素を走査。
    # x:: どの位置で走査するか
    # returns:: 指定された軸の上にドットが存在: false, 無い: true
    def vline_blank?(x)
      for y in 0...@height
        return false if self[x, y] == BLACK
      end
      return true
    end

    # 上下のマージン削除した新しいPixelMatrixを返す。
    # returns:: PixelMatrix
    def cutoff_vmargin
      pixel = PixelMatrix.new(0, 0, true)
      head = 0
      tail = self.height - 1

      head.upto(tail) do |y|
        if !self.hline_blank?(y) then
          head = y
          break
        end
      end
      tail.downto(head) do |y|
        if !self.hline_blank?(y) then
          tail = y
          break
        end
      end

      head.upto(tail) do |y|
        0.upto(self.width - 1) do |x|
          pixel[x, y - head] = self[x, y]
        end
      end

      return pixel
    end
    
    # 自身の上下のマージン削除する。cutoff_vmarginの破壊版。
    # 速度稼ぎのために直接@matrixを触ったり、すこしずるをしている。
    # 効率は、ほんの少しだけ速くなったような誤差の範囲のような感じ。
    # returns:: self (PixelMatrix)
    def cutoff_vmargin!
      head = 0
      tail = self.height - 1

      head.upto(tail) do |y|
        if !self.hline_blank?(y) then
          head = y
          break
        end
      end
      tail.downto(head) do |y|
        if !self.hline_blank?(y) then
          tail = y
          break
        end
        @matrix.delete(y) if @matrix.has_key?(y)  # XXX
      end

      if head > 0 then
        head.upto(tail) do |y|
          next if !@matrix.has_key?(y)            # XXX
          @matrix[y - head] = @matrix.delete(y)   # XXX
        end
      end
      self.height = tail - head + 1

      return self
    end
    
    def each_with_axis
      for x in 0...@width
        for y in 0...@height
          yield(x, y)
        end
      end
    end
  end
end

class DeCAPTCHA::Site::YourFileHost::Token
DIGITS_ASSOC = [
  # 0
  ["00000000011111110000000000",
   "00000001111111111110000000",
   "00000011111000001111000000",
   "00001111111100010011110000",
   "00011111100000110000111000",
   "00111111000000100001111000",
   "00111111110001000001111100",
   "01111111000010000011111110",
   "01111100000110000111111110",
   "01111111000100000111111110",
   "11111100001000001111111111",
   "11100000001000011111111111",
   "11111000010000011111111111",
   "11111000110000111111111111",
   "10000000100001111111111111",
   "01100001000001111111111110",
   "01100010000011111111111110",
   "01100010000111111111111110",
   "00111100000111111111111100",
   "00011100001111111111111000",
   "00001100011111111111111000",
   "00001111111111111111100000",
   "00000011111111111111000000",
   "00000000111111111100000000"],
  # 1
  ["00001",
   "00111",
   "11111",
   "11111",
   "10001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001"],
  # 2
  ["0000011111111110000000",
   "0001111111111111000000",
   "0011110000000010000000",
   "0110000000000100000000",
   "1100000000001100011110",
   "1000000000001000001111",
   "1000000000010000000111",
   "1000000000110001111111",
   "1000000000100001111111",
   "1000000001000000011111",
   "0100000011000001111111",
   "0011000010000111111110",
   "0011000110000001111110",
   "0000001100000111111100",
   "0000001000011111110000",
   "0000011000000111100000",
   "0000110000000000000000",
   "0000111111111111111111",
   "0001111111111111111110",
   "0011111111111111111100",
   "0011111111111111111100",
   "0111111111111111111000",
   "0111111111111111110000"],
  # 3
  ["000000011111111110000000",
   "000001111111111111100000",
   "000011100000011111111000",
   "000111000000111111111000",
   "000110000001111111111100",
   "000100000001111111111100",
   "000100000011111111111100",
   "000110000111111111111000",
   "000010000111111111111000",
   "000000001111111111100000",
   "000000011111111111000000",
   "000000011111111110000000",
   "000000000000001100000000",
   "000000000000011100011100",
   "000000000000111000111110",
   "000000000000110000001110",
   "000000000001110001111111",
   "110000000011100011111111",
   "111000000111000000111110",
   "011100000110001111111100",
   "001111001110000111111000",
   "000011111100000011100000",
   "000000011000111000000000"],
  # 4
  ["0000000000011",
   "0000000000011",
   "0000000000111",
   "0000000001111",
   "0000000001111",
   "0000000011111",
   "0000000111111",
   "0000000110111",
   "0000001100111",
   "0000011100111",
   "0000011000111",
   "0000110000111",
   "0001110000111",
   "0001100000111",
   "0011000000111",
   "0111000000111",
   "0111111111111",
   "1111111111111",
   "0000000000111",
   "0000000000111",
   "0000000000111",
   "0000000000111",
   "0000000000111"],
  # 5
  ["000000001111111111111110",
   "000000011111111111111100",
   "000000111111111111111100",
   "000000111111111111111000",
   "000001111111111111110000",
   "000011100000000000000000",
   "000011011111111110000000",
   "000111111111111111000000",
   "001111100000000111000000",
   "001110000000000110001100",
   "000000000000000100011110",
   "000000000000001100000110",
   "000000000000011000011111",
   "000000000000011001111111",
   "000000000000110000011111",
   "000000000001100000111111",
   "110000000001100111111110",
   "011000000011000001111110",
   "011100000110000011111100",
   "001111000110011111111000",
   "000111111100001111110000",
   "000001111100000011000000",
   "000000001000011000000000"],
  # 6
  ["000000000000000110000000",
   "000000010001111111111000",
   "000001110000011100111100",
   "000011100000011000001000",
   "000111000011111000000000",
   "001111000001110000000000",
   "001110000000111100000000",
   "011110001111111111100000",
   "011100000111000011110000",
   "011000000010000001111000",
   "011000011110000011111100",
   "010000111100000111111110",
   "100000001000000111111110",
   "100001111000001111111111",
   "000011110000011111111111",
   "000000100000011111111111",
   "000011100000111111111111",
   "001111000001111111111110",
   "000010000001111111111110",
   "001110000011111111111100",
   "000111000111111111111000",
   "000011111111111111110000",
   "000000111111111111000000",
   "000000000111111000000000"],
  # 7
  ["0011111111111110001111",
   "0011111111111100000011",
   "0111111111111000000110",
   "1111111111111000111100",
   "1111111111110000001100",
   "0000000000000000011000",
   "0000000000000011111000",
   "0000000011000000110000",
   "0000001110000011100000",
   "0000011110001111100000",
   "0000111100000011000000",
   "0001111000000110000000",
   "0001111000111110000000",
   "0011110000001100000000",
   "0011110000001000000000",
   "0011100011111000000000",
   "0011000001110000000000",
   "0001000000110000000000",
   "0000000111100000000000",
   "0000000111000000000000",
   "0000000011000000000000",
   "0000001110000000000000",
   "0000001100000000000000"],
  # 8
  ["0000000111111111110000000",
   "0000011111111111111100000",
   "0000001111100000011110000",
   "0000000001110000000111000",
   "0011000011111000000011100",
   "0011100001111100000011100",
   "0011110000001110000011100",
   "0001111000011111000111000",
   "0000111100000111101110000",
   "0000011110000001111100000",
   "0000001111000011111110000",
   "0000111111110000011111000",
   "0011110011111000001111100",
   "0111100001111100011111100",
   "0111000000111110000111110",
   "1111000000011111000000111",
   "1111000000001111100011111",
   "1111000000000011111000010",
   "0111100000000001111100000",
   "0011110000000000111110000",
   "0001111110000001111110000",
   "0000011111111111111000000",
   "0000000011111110000000000"],
  # 9
  ["000000111111111110000000",
   "000001111111111111100000",
   "000111111111111001111000",
   "001111111111110000010000",
   "011111111111110000010000",
   "011111111111100000100000",
   "011111111111000001100000",
   "111111111110000001000111",
   "111111111110000010000001",
   "111111111100000110000111",
   "011111111000000100011111",
   "011111111000001000001111",
   "001111110000011000011111",
   "001111100000010001111110",
   "000111110000100000011110",
   "000001111111100000111110",
   "000000011111000111111100",
   "000000000010000001111100",
   "000000000110000001111000",
   "000100001100011111110000",
   "000111001100001111100000",
   "000011111000001111000000",
   "000000010000110000000000"],
]
end
__END__

2008-10-06

YourFileHostのCAPTCHA画像をなんとかする

破ろうぜ!CAPTCHA画像♪(うっうーん)

そんなわけで、みんな大好きなYourFileHostだけども、最近みてみたら、なんかCAPTCHA認証がついているわけじゃないですか。

でもこれってさーCAPTCHAといっても見るからに危ういというか、見れば見るほど簡単に破れてしまいそうな気がして、どうにもむずがゆいアンニュイな気分になってしまうわけです。

そんで、このたび適当にいじってみたところ、それなりに推測できるコードが書けたので、ここに張ってみますね。

やってることは単純で、こんな感じ

  1. CAPTCHA画像ファイルをよみこむ
  2. ピクセルごとにグレイスケールにして、それで2値にする
  3. この時点でじゃまな背景が消えて、文字の形がわかってしまうわけです
  4. 縦軸に点がないところで切って、文字ごとにばらばらにする
  5. 文字画像のサンプルと比較して、一致率が高いものを採用

使い方は、こんな感じで

require 'decaptcha.rb'
captcha_string = DeCAPTCHA.decode(filename)
if !captcha_string.nil? then
  # 判別成功時の処理
else
  # 判別失敗時の処理。失敗することもあるのでよしなに。
end

あ、Ruby/GD2入れといてね。sudo gem install gd2とかで入ります。多分。

判別率はそこそこ良い感じになったんだけども、富豪プログラミングがたたってか、いかんせん遅いです。

手元だと1枚判別するのに20秒くらいかかることもある。

そんなわけで誰かチューニングしてくれるとうれしい。

追記

実行速度を上げた改良版はこっちにうpしました。以下のコードは参考程度に。

コード (decaptcha.rb)

#!/usr/local/bin/ruby
require 'rubygems'
require 'gd2'
require 'pp'

#
#= CAPTCHA画像解析モジュール
# CAPTCHA画像ファイルを食わすとあら不思議Stringが出てくるよ。
# YourFileHostのやつに対応。
#
#== Usage
# decoded_str = DeCAPTCHA.decode("some_captcha_image.gif")  #=> String
# 失敗したらnilが返る。
#
module DeCAPTCHA
  DEBUG = false

  #=== CAPTCHA画像デコード
  # file::    画像ファイル名のパス
  # method::  未指定でよい。男は細かい事を気にするな。
  # returns:: CAPTCHA画像解析結果(String) or nil (デコード失敗時)
  def self.decode(file, method = DeCAPTCHA::Site::YourFileHost)
    return method.new(file).decode
  end



  #= CAPTCHA画像デコードクラス
  # このクラスサブクラスはimport, tokenize, stream_parseメソッドの
  # 実装を含む必要がある。
  class Site
    def initialize(file = nil)
      @pix = nil
      self.import(file) unless file.nil?
    end
    def decode
      return stream_parse(tokenize())
    end
  end

  #= YourFileHostのCAPTCHA画像を解析するクラス
  class Site::YourFileHost < Site
    def import(file)
      @pix = PixelMatrix.new.import(file)
      return self
    end

    # importしたイメージ(PixelMatrix)から、文字と思わしきパターンを
    # 抽出して上下マージンを切り取ってArrayにして返す。
    # returns:: Array of PixelMatrix
    def tokenize
      getter, tokenizer = lambda {|queue|
        [ lambda { return queue },
          lambda {|x, pixel|
            if pixel.nil? then
              x, pixel = tokenizer.call(x, PixelMatrix.new(0, 0, true))
              queue << pixel
              return x
            end
  
            if !@pix.in_range?(x, 0) or @pix.vline_blank?(x) then
              return [x, pixel]
            end
            x0 = pixel.width
            @pix.vline(x).inject(0) do |y, color|
              pixel[x0, y] = color
              y + 1
            end
            return tokenizer.call(x + 1, pixel)
          }
        ]
      }.call([])

      x = 0
      while (x < @pix.width)
        x = @pix.vline_blank?(x) ?
          x + 1 :
          tokenizer.call(x, nil)
      end

      getter.call.map do |token|
        # Token.new.import(token.cutoff_vmargin.shrink)
        Token.new.import(token.cutoff_vmargin)
      end
    end

    # PixelMatrixのArrayを受け取り、数字を判別。
    # tokens:: Array of PixelMatrix
    # returns:: String (判別結果)
    def stream_parse(tokens)
      r = []
      tokens.inject(nil) do |prev, cur|
        r << cur.guess
      end

      rs = r.map {|x| x.to_s}.join('')
      if rs.length != 4 then
        if DEBUG then
          puts '- guess failed. dumping guess result of each token:'
          tokens.each_index do |i|
            print "##{i}: "
            pp tokens[i].candidate
          end
          puts
        end
        return nil
      end
      return rs
    end

    class Token
      @@digits = nil
      attr_accessor :candidate

      def initialize
        if @@digits.nil? then
          # 文字画像サンプルを作っておく
          @@digits = DIGITS_ASSOC.map {|assoc|
            PixelMatrix.new(0, 0, true).import_assoc(assoc) }
        end

        @candidate = Hash.new
      end

      # PixelMatrixを受け取り、文字画像サンプルと比較して
      # 一致率を計算しておく。
      # pixel:: PixelMatrix
      # returns:: self
      def import(pixel)
        gcd = lambda {|a, b|
          a, b = [b, a] if a < b
          return a if b == 0
          r = a % b
          return gcd.call(b, r)
        }
        lcm = lambda {|a, b| a * b / gcd.call(a, b) }
        mul_to_lcm = lambda {|a, b|
          g = gcd.call(a, b)
          [b / g, a / g]
        }

        0.upto(@@digits.size - 1) do |i|
          if (@@digits[i].width - pixel.width).abs   > 4 or
             (@@digits[i].height - pixel.height).abs > 4 then
            @candidate[i] = -1  # 比較対象とサイズが違いすぎ
            next
          end

          mul_ax, mul_bx = mul_to_lcm.call(@@digits[i].width,  pixel.width)
          mul_ay, mul_by = mul_to_lcm.call(@@digits[i].height, pixel.height)
          enlarged_width  = @@digits[i].width  * mul_ax
          enlarged_height = @@digits[i].height * mul_ay

          # 文字画像サンプルと比較対象画像のサイズをあわせる
          # 幅・高さをそれぞれ適当整数倍して、最小公倍数に合わせて比較
          # (めんどうだから)
          correct_bits = 0
          (0...enlarged_width).each do |x|
            (0...enlarged_height).each do |y|
              if @@digits[i][x/mul_ax, y/mul_ay] ==
                 pixel[x/mul_bx, y/mul_by] then
                correct_bits += 1
              end
            end
          end
          
          @candidate[i] = correct_bits * 100 /
                          (enlarged_width * enlarged_height)
        end

        return self
      end

      # importのときの比較結果をもとに文字を推測
      # returns:: Fixnum or nil(失敗時)
      def guess
        digit, ratio = @candidate.sort {|a, b| a.last <=> b.last}.last
        digit = nil if ratio < 0 or ratio < 80
        return digit
      end
    end
  end


  #= 画素マトリックスクラス
  # 画像ファイルを食わせると、各ピクセル(画素)を2値(black(1) or white(0))に
  # 変換して、内部で保持する。
  # 以後、Matrixクラスのような感じで個々の画素アクセスできる。
  class PixelMatrix
    BLACK = 1
    WHITE = 0

    attr_accessor :width
    attr_accessor :height

    # width::  幅
    # height:: 高さ
    # is_flexible:: 自動的に伸張するか
    def initialize(width = 0, height = 0, is_flexible = false)
      @matrix = Hash.new {|hash, key| hash[key] = Hash.new(WHITE)}
      @width, @height, @flexible = width, height, is_flexible
    end

    # file:: 画像ファイル名のパス
    # brightness_threshold:: 画素を黒とみなす閾値 (0 - 255, default: 0x40)
    # returns:: self (DeCAPTCHA::PixelMatrix)
    def import(file, brightness_threshold = 0x40)
      gd = GD2::Image.import(file)
      @width, @height = gd.width, gd.height

      self.each_with_axis do |x, y|
        color = gd[x, y]
        greyscale = (color.red + color.green + color.blue) / 3
        self[x, y] = (greyscale > brightness_threshold) ?
          WHITE :
          BLACK
      end
      return self
    end

    # reverse function of to_assoc
    def import_assoc(assoc)
      assoc.inject(0) do |y, columns|
        columns.inject(0) do |x, color|
          self[x, y] = color
          x + 1
        end
        y + 1
      end
      return self
    end

    # PixelMatrixを画像ファイルとしてexport
    # file:: 新たに作る画像ファイル名のパス
    def export(file)
      gd = GD2::Image::IndexedColor.new(@width, @height)
      gd.palette << GD2::Color::WHITE
      gd.palette << GD2::Color::BLACK
      self.each_with_axis do |x, y|
        gd[x, y] = {
          WHITE => GD2::Color::WHITE,
          BLACK => GD2::Color::BLACK,
        }[self[x, y]]
      end
      gd.export(file)
      return self
    end

    def to_assoc
      (0...@height).map do |y|
        (0...@width).map do |x|
          self[x, y]
        end
      end
    end

    # 指定された位置の画素を返す。
    # returns:: PixelMatrix::BLACK(1) or WHITE(0)
    def [](x, y)
      if !@flexible and !in_range?(x, y) then
        raise RangeError
      end
      return @matrix[y][x]
    end

    # 画素に値を設定。
    # returns:: PixelMatrix::BLACK(1) or WHITE(0)
    def []=(x, y, val)
      unless in_range?(x, y) then
        raise RangeError unless @flexible
        @width  = (x >= @width)  ? x + 1 : @width
        @height = (y >= @height) ? y + 1 : @height
      end

      @matrix[y][x] = val
    end

    def in_range?(x, y)
      ((0...@width) === x and (0...@height) === y)
    end

    # 指定された軸をもとに画素を走査し、Arrayに変換。
    # 例えば、to_a(:vertical, 10) とすると、x == 10 な列を取り出して
    # Arrayにして返す。
    #
    # axis:: 軸を指定 (:vertical または :horizontal)
    # pos:: 位置を指定。_axis_で指定した軸と直交する軸における位置を指定。
    def to_a(axis, pos)
      {:vertical => lambda {
        (0...@height).map {|y| self[pos, y]}
       },
       :horizontal => lambda {
        (0...@width).map  {|x| self[x, pos]}
       },
      }[axis].call
    end

    # returns:: Array
    def hline(y)
      self.to_a(:horizontal, y)
    end

    # returns:: Array
    def vline(x)
      self.to_a(:vertical, x)
    end

    # X軸方向に画素を走査。
    # y:: どの位置で走査するか
    # returns:: 指定された軸の上にドットが存在: false, 無い: true
    def hline_blank?(y)
      hline(y).find {|color| color == BLACK }.nil? ?
        true : false
    end

    # Y軸方向に画素を走査。
    # x:: どの位置で走査するか
    # returns:: 指定された軸の上にドットが存在: false, 無い: true
    def vline_blank?(x)
      vline(x).find {|color| color == BLACK }.nil? ?
        true : false
    end

    # 上下のマージン削除した新しいPixelMatrixを返す。
    # returns:: PixelMatrix
    def cutoff_vmargin
      pixel = PixelMatrix.new(0, 0, true)
      head = 0.upto(self.height - 1) do |y|
        break(y) if !self.hline_blank?(y)
      end
      tail = (self.height - 1).downto(0) do |y|
        break(y) if !self.hline_blank?(y)
      end

      head.upto(tail) do |y|
        y0 = pixel.height
        self.hline(y).inject(0) do |x, color|
          pixel[x, y0] = color
          x + 1
        end
      end

      return pixel
    end
    
    def each_with_axis
      (0...@width).each {|x|
        (0...@height).each {|y|
          yield(x, y)}}
    end
  end
end

class DeCAPTCHA::Site::YourFileHost::Token
DIGITS_ASSOC = [
# 0
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
 [0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]
],
# 1
[[0, 0, 0, 0, 1],
 [0, 0, 1, 1, 1],
 [1, 1, 1, 1, 1],
 [1, 1, 1, 1, 1],
 [1, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1]],
# 2
[[0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
 [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1],
 [0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
 [0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]],
# 3
[[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
 [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0],
 [0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
# 4
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1]],
# 5
[[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1],
 [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0],
 [0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
# 6
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
 [0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
# 7
[[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1],
 [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
# 8
[[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
 [0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
 [0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
 [0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0],
 [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1],
 [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0],
 [0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
# 9
[[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1],
 [0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1],
 [0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0],
 [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
]
end


__END__
Dir.glob('*.gif').each do |file|
  puts "Processing file: #{file}"
  p DeCAPTCHA.decode(file)
end

__END__

2008-02-12

うつと社会的地位

スーザン・グリーンフィールド『脳の探求』より

セロトニンうつ状態のつながりに熱狂するあまり、それを社会的地位の説明にまで拡大する科学者もいる。オナガザルの研究で、社会的階層の底辺にいるサルセロトニンの濃度が低く,頂点にいるサルは高いということがあきらかにされている。地位が上がると、セロトニンの濃度も高くなる。同じように、人間社会でも、地位の低い人(貧困者や女性)はセロトニンの濃度が低くなる傾向にあり、実際、うつ病は比較的このグループに多い。うつ病は、社会のより優位なグループメンバーに対して、地位を表明する手段として進化したという説もある。内向的でひかえめな行動は、将来ライバルとなるおそれがないことを示し、地位の高い者を安心させるというわけだ。(pp.188-190)

グリーンフィールド自身がこの説に賛同しているわけではないが、個人的には強く興味をひかれた。

2008-01-11

1962年の「恋愛資本主義

ずいぶん久しぶりに社会学の書棚にいったらブルデューの『結婚戦略家族階級再生産』という本の翻訳が出ていたのでついつい買ってしまいました。

下の引用は旧来の家中心の婚姻システムが崩れ、自由恋愛システムが立ち現れ始め、農民=ダサイ、都会人=イケてる、という対立が明らかになってきた時期のフランスのど田舎農村について記述です。それが1962年に書かれた論文のものだということを考えると、今になって「恋愛資本主義」だなんだとさわいでいるのがばからしく思えてきました。

クリスマスダンスパーテーが、とあるカフェの奥のホールでおこなわれている。(・・・)フロアの周縁につっ立って暗い塊をなしている一段の年長の男たちが押し黙ったまま見物している。(・・・)独り者が皆、そこに揃っているのだ。(・・・)クリスマス元日ダンスパーティーでは、独り者たちは何もすることがない。(・・・)独り者連中は夜中までそこにいるだろう。パーティーの明かりと賑わいの中、ほとんど無言のまま、近づくことのできない娘たちを見やりながら。そのあと彼らはカフェの奥に行き、向かい合って飲むことだろう」(pp.7-8)

「たとえ少しでもぎこちなかったり、無精ひげが生えていたり、みっともない身なりをしていれば、農民は即座に『ふさぎの虫にとりつかれた、不器用な、気むずかしい、時には、下品な、女にたいしてつっけんどんな』、社交的でなく無愛想なフクロウと見なされてしまうのである」(p.136)

「自らの身体に関する惨めな意識は、(都会人とは異なり)農民を自分の身体から切り裂き、内向的な態度にさせる。こうした態度こそが臆病さとぎこちなさの根源にあり、彼にダンスを禁じ、女性の前で単純で自然な態度をとることを禁じるのである。結局のところ農民は、自らの身体に当惑しているために、我を忘れさせ、自らの身体を衆目にさらすようなあらゆる機会のなかで、気詰まりやぎこちなさを感じてしまうのである」(p.137)

経済的・社会的条件が結婚への適性に影響を及ぼすのは、主として男性がこうした条件について抱いている意識を媒介にしてなのである。要するに、自覚のある農民とは、軽蔑的な意味での農民として自らをとらえる機会をいくどとなく持たされてしまった農民なのである」(p.138)

ピエールブルデュー(2007)『結婚戦略家族階級再生産』藤原書店

2007-12-08

PPパナップって何者?

2007-11-17

土曜日、朝9時起床。

現在、昼。

ニコニコ動画を見る。

いつも見ている永井先生を検索、過去動画を見ていた。

釣り動画を見つける、見てみる、変な奴がしゃべっている

タグの一部を押す、同じく配信者のゆとりポスというのが映る。

変なきちがいにしか見えない。でも、発作時の自分に似ているので落ち込んだ。

PPパナップを見る。気持ち悪い。でも、どこか自分に似ているので落ち込んだ。

2007-11-10

殿堂入りができない

こんにちは ぼくはポケモンが大好きです。

しかし、ポケモンであることができません。

それは、殿堂入りができないことです。

そのことをみんなに伝えようとぼくは自分を元にした歌を作りました。

この歌で、できないことをできるには、自分でやらなきゃいけないと思って欲しいです。

それでは聞いてください 「殿堂入りができない」


殿堂入りができない 原曲・「エアーマンが倒せない

気がついたらいつも「そらをとぶ」をばかりしてる、そしていつもポケモンが育たない

あきらめずにいっぱいトレーナーとバトルをするけど すぐに飽きてしまうよ

ふしぎなアメがあれば 楽にポケモン強くなるけれど

何回やっても 何回やっても 殿堂入りができないよ

あの四天王 何回やっても 倒せない

必死に強いわざをだしても すぐにPPなくなる

伝説のポケモンも試してみたけど レベルが低けりゃ意味がない

だけど次は絶対勝つから 僕は「かいふくのくすり」を最後までとっておく


気がついたらつかまえた数が少なく、みつけた数の半分以下だった

あきらめずに草むらとかを必死にはしるけど いつも同じポケモン

マスターボール」があれば 楽にポケモンゲットできるけど

何回やっても 何回やっても ポケモンつかまらないよ

あのポケモン 何回やっても つかまらない

必死にボールをなげたけれど すぐにボールがなくなる

HPをギリギリにしてみたけど 「じこさいせい」をつかったら意味がない

だけど次は絶対ゲットするから 僕は「タイマーボール」を最後までとっておく


「わざマシン」があれば楽に強いわざをおぼえるけど

何回やっても 何回やっても チャンピオンが倒せないよ

あのチャンピオン 弱点ないから 倒せない

必死にダメージをあたえるけど チャンピオンが回復してくる  

強いわざを出してみたけど 効果がなかったら意味がない

だけど次は絶対勝つから 僕は「げんきのかたまり」をちかつうろで掘っておく(END)


この歌のご意見・ご感想トラックバックで募集します。

そしてこの歌がニコニコ動画流行るのが、ぼくの夢です。

- 転職ならen
- 派遣ならen
2ページ中1ページ目を表示(合計:28件)