スキップしてメイン コンテンツに移動

投稿

小学3年生の授業参観でアルゴリズムに出会った

小学3年生の娘の日曜授業参観に行ってきた。算数の授業だ。授業の後半、以下のような問題が出された。 問題 : ゴマダラチョウとトノサマバッタがあるゲームをしている。0から9までの数字の書かれたカードがそれぞれ一枚ずつ全部で10枚あって、それを使って3桁の数を2つ作り、その差をできるだけ小さくした方が勝ちとなるゲームだ。ただし百の位は0にできない。できるだけ小さくするにはどのようにカードを選べばよいだろうか。 これを約30人の生徒に考えさせていた。解き方を先に教えるということはしない。生徒が問題を考えている間、先生は生徒たちを見回り、質問などに答える。しばらくするといろいろと答えが挙がってきた。自分の娘は以下のように考えたようだ。 百の位は差が1であればどの数字でも良いので、まず十の位を最小にする数字を考えてみると、最小の数字0から最大の数字9を引いた場合が最も小さくなる。同様に一の位では0と9以外の最小・最大の数字を選ぶ。つまり1から8を引いた場合が最小になる。百の位は残りの数字カードから差が1となるものを選ぶ。解答例は「501-498」や「701-698」となり、差は3になる。 これはまさにアルゴリズムだ。Pythonであれば以下のコードと同じだろう。 digits = range(10) ten = (digits.pop(), digits.pop(0)) one = (digits.pop(), digits.pop(0)) idx = random.randrange(len(digits) - 1) hund = (digits.pop(idx), digits.pop(idx)) a = reduce(lambda x, y: x * 10 + y, map(array, (hund, ten, one))) print "%d - %d = %d" % (a[1], a[0], a[1] - a[0]) 出力例: 601 - 598 = 3 小学3年生の算数だと思ってそれほど期待せずに観に行ったのだが、生徒たちはみな楽しそうに問題に取り組んでいたし、なかなか面白い授業をしているようで何だか安心した。因みに、今回のようなクラス全員で考える問題は普段からよく行っているとのことだった。

スーパーコンピュータとプログラミング言語

世の中には星の数ほどのプログラミング言語があるかもしれないが、スーパーコンピュータで利用するとなるとかなり限られてくる。ライフサイエンス分野のデータの処理にはPython、Ruby、Perlなどのいわゆるスクリプト言語はよく使われるし、データベース関連だとJavaなどもあるだろう。しかし科学技術計算に限れば、FortranやC/C++が多数を占めると思う。やはり実行効率と既存資産の存在は大きい。 数値計算プログラムでは、とにかく速さが求められる。どれだけの速さがあれば十分かだって? この質問はナンセンスだと思う。たとえ現在の最高速度を誇るスーパーコンピュータの1億倍の速度があったとしても十分ではない。使える資源でできる範囲の計算をするだけなのだから。 自分の携わる分野では一回の計算に半年かかることもざらなので、計算速度は死活問題だ。1分で終わる処理なら倍に高速化したとしても差は30秒でしかない。しかし、半年となるとその差は3ヶ月にもなる。だから、Fortranを使うにしても、よりモダンなFortran90/95だけではなく、 古めかしいが実行速度の速いFORTRAN77 もよく使われる。まあ、最近は速度差も縮まってきているのでそこまでFORTRAN77にこだわらなくなってきているけど。本当にクリティカルな部分にはアセンブリ言語なども使われている。 また、汎用コンピュータのコンパイラに比べてスーパーコンピュータに最適化されたコンパイラではバグの入っていることが多く、C++でもBoostなどの外部ライブラリは避けた方が無難だ。使うにしても GoogleのC++コーディング規約 のように一部に限定して使う方が良い。実際にBoost絡みのコンパイラバグによる混乱を見るに、STLなどの標準ライブラリのみをシンプルに利用していた方がまだ安全だ(それでもバグるけど)。そうは言ってもBoostは便利なのでできるだけ早くC++0xの標準化がされてほしい。標準化されていればコンパイラベンダも言い訳できないしね。 そういえば Fortress なんて言語もあるね。面白い試みではあるけれど現状で利用するのは難しいような気がするなぁ。特に冒頭でも述べた、Fortranと同程度の実行効率が出せるかという点と既存資産の代替が存在するのかという点で。因みにFortressでの...

OAuthを使ってAndroidからPythonでTwitterに投稿する

以前、 ASE (Android Scripting Environment) を使って「 AndroidからPythonでTwitterに投稿する 」という記事を書いたが、来月末にTwitterのBASIC認証が廃止されるので使えなくなる。そこで、OAuthを利用するコードに書き直してみた。最近はAndroidの twicca がとても使いやすいのでPythonスクリプトによるTwitterへの投稿もあまりないかもしれないが、Android端末単体でOAuthを利用したTwitterの認証ができることを示す意味でも公開することにした。 まず、「 コマンドラインで動作するOAuth対応TwitterクライアントをPythonで作ってみた 」という記事で用意したoauth.pyとoauthtwitter.pyをAndroid機の/sdcard/ase/scripts/ディレクトリにコピーする。これは adb pushでコピー してもいいし、SDカードに直接コピーしてもいい。oauthtwitter.pyは一部修正してあるので上述記事の該当箇所を参照して書き直して欲しい。 次に、それらのライブラリを利用して以下のようなコードを書いた。赤字で示した認証コードの部分はTwitterのサイトの OAuthクライアント登録 で取得する必要がある。 tw_oauth_ase.py #!/usr/bin/env python # -*- coding: utf-8 -*- import os, pickle, time, android from oauthtwitter import * CONSUMER_KEY = " CONSUMER_KEY " CONSUMER_SECRET = " CONSUMER_SECRET " KEY_FILE = "/sdcard/ase/scripts/twitter_key.dat" droid = android.Android() def twitter(): if os.path.isfile(KEY_FILE): access_token = pickle.load(file(KEY_FILE)) else: ...

C++0xでYコンビネータ

stackoverflow.com の Fixed point combinators in C++ (C++による不動点結合子)に載っていたC++とboostで書かれたYコンビネータ(Y combinator)のサンプルコードをC++0xを使って書き直してみた。C++0xだと標準ライブラリだけでこれだけ簡潔に書ける。 #include <iostream> #include <functional> using namespace std; // Y-combinator for the int type function<int(int)> y(function<int(function<int(int)>, int)> f) { return bind(f, bind(&y, f), placeholders::_1); } int main() { // Y-combinator compatible factorial auto fact = [](function<int(int)> f, int v){ return v == 0 ? 1 : v * f(v - 1); }; auto factorial = y(fact); cout << factorial(5) << endl; return 0; }

一行でテキストに含まれるURLをすべて短縮URLに変換するPythonスクリプト

テキストに含まれるURLをすべてbit.lyの短縮URLに変換するPythonワンライナーを書いた。使用しているモジュールはre、urllib、urllib2、simplejson。コードに一行追加するだけだし、Twitterなどのメッセージを処理するのに便利だと思う。 for link in sorted(re.findall(r"(http(?:s?)\:\/\/(?!bit\.ly[\/\ ])[^\/\ ]+\/?.*?)(?:[\ <>\"\{\}\|\\\^\[\]\`]|$)", msg), reverse=True): msg = (lambda x: re.sub(re.escape(x), (lambda y: str(simplejson.loads(urllib2.urlopen("http://api.bit.ly/shorten?version=2.0.1&longUrl=%s&login= BITLY_ID &apiKey= BITLY_API_KEY " % urllib.quote(y)).read())["results"][y]["shortUrl"]))(x), msg))(link) bit.lyのAPIキーは 別途取得 しておく必要がある。 msg = u"ここのブログのURLはhttp://handasse.blogspot.com/ です。記事のURLはhttp://handasse.blogspot.com/2010/05/urlurlpython.html です。" としてURLを含むメッセージを処理すると以下のように変換される。 print msg ここのブログのURLはhttp://bit.ly/PQa9F です。記事のURLはhttp://bit.ly/cVRVu6 です。 上記のコードを展開したものが以下のコード。簡単なエラー処理を追加してある。 def bitly(x): try: data = urllib2.urlopen("http://api.bit.ly/shorten?version=2....

コマンドラインで動作するOAuth対応TwitterクライアントをPythonで作ってみた

6月末にTwitter APIのBASIC認証が終了してしまうので、OAuth対応のTwitterクライアントを作ってみることにした。とりあえず最もシンプルだと思われるコマンドラインで動作するクライアントをPythonで作成してみた。 まず、Twitterクライアントを作成する前に、Twitterのサイトで OAuthクライアントの登録 を行わなくてはならない。ここで、「アプリケーーション名」、「アプリケーションの説明」、「アプリケーションのウェブサイトURL」を記入する必要がある。また、今回はPC上で実行するクライアントで読み書きを行いたかったので、「あなたの招待状」には「送信」、"Default Accdess type"には"Read & Write"を選択した。 登録を済ますと、"Application Details"のページで"Consumer key"と"Consumer secret"が与えられるので、これを作成するアプリケーションで利用する(CONSUMER_KEY, CONSUMER_SECRET)。 次にコーディングだが、できるだけ短くシンプルに作りたかったので、Python外部モジュールの twitter 、 oauth 、 oauthtwitter を利用させてもらうことにした。ただ、 作者のページ のコードでは途中でエラーになってしまうので、 oauthtwitter.pyのOAuthApiクラスのgetAccessTokenメソッドの下に以下のgetAccessTokenWithPinメソッドを追加した。 def getAccessTokenWithPin(self, pin, url=ACCESS_TOKEN_URL): token = self._FetchUrl(url, parameters={"oauth_verifier": pin}, no_cache=True) return oauth.OAuthToken.from_string(token) 今回作成したTwitterクライアントの使い方だが、 tw.py で最新のタイムラインを表示する。取得件数...

Google App EngineとSafe Browsing APIを利用して短縮URLチェッカーを作ってみた

最近、Twitterやはてなブックマークなどを使うことが多くなり、字数制限付きのコメントを書くことが増えた。コメント中にURLを入れたいこともままあるのだが、長いURLだと字数をオーバーしてしまう。そのため短縮URLを使っているが、コメント内に直接短縮URLを入れるのがやっかいだった。そこで、 Google App Engine (GAE) を使ってシンプルで高速な短縮URL変換ツールを作成してみた。 しかし、短縮URLは悪意のあるサイトの判別が難しいという欠点がある。見た目で判断できないので開くのを躊躇してしまう。そこで、今回作成したツールでは、短縮URLに変換するだけではなく、それを元のURLに戻す機能も追加した。さらに、 Google Safe Browsing API を利用してフィッシングサイトなどの悪意あるサイトの判別も試みている。 短縮URLチェッカー 使い方はシンプルで、テキストボックスに変換したいURLを入力すればbit.lyの短縮URLがテキストボックス表示され、bit.lyの短縮URLを入力すればもとのURLが表示される。テキストボックスをクリックすれば表示されているURLが選択されるのでクリップボードへのコピーも簡単だ。テキストボックスの下には展開されたURLがリンク付きで表示されるが、もしフィッシングサイトだと疑われる場合は、以下のように警告してくれる。 さて、今回のコード作成だが、bit.lyによる短縮URLの変換は簡単だった。というのも 以前にPythonスクリプトで作った ことがあるからだ。それをそのままGAEに載せればいい。しかし、Safe Browsing APIによる悪意あるサイトの検出は思ったよりも面倒だった。まず、APIの使い方がよく分からない。使う前は任意のURLをAPIで確認するのかと思っていたのだが、そうではなく、MD5でハッシュ化したリストをダウンロードして、調べたいURLをハッシュ化してそれと照らし合わせなくてはならない。今回問題になったのはそのダウンロード容量で、フィッシングサイト用データが700KB程、マルウェア用データが10MBを超えていた。GAEでは一回のダウンロード容量の上限が1MBと決まっており、フィッシングサイト用データは何とかダウンロードできても、マルウェア用データは途中で切れ...