ProjectEuler.vim : VimからProjectEuler
ProjectEulerとは?
ProjectEulerとは、プログラムで解く数学の問題集です。
公式サイト:About - Project Euler
つまり、数学的知識が必要で、かつプログラムを組まないととてもじゃないけど解けない問題が多数公開されています(2009-2-24時点で279問あります)。ユーザー登録することで問題に解答できるようになります。問題の日本語訳は以下のサイトにあります。
日本語訳:Project Euler - PukiWiki
インストール方法
ソースは GitHub - mmisono/ProjectEuler.vim: vim plugin for Project Euler (http://projecteuler.net) にあります(gitとかはじめて使った)。
- plugin/projecteuler.vim
- syntax/projecteuler.vim
- syntax/projecteulerP.vim
- doc/projecteuler.txt
- projecteuler (空ディレクトリ)
以上のファイル/ディレクトリを適当な場所に置いて、パスを通して下さい。
helptag path-to/doc/ でヘルプが追加されます。
コマンド一覧
:ProjectEuler [id]
Problem
idが指定されなかった場合はファイル名から推測、それでも分らなかった場合尋ねます。
:ProjectEuler -l [pagenr]
問題のリストの1ページ目を表示します。
pagenrを指定すればそのページのリストを表示します。
:ProjectEuler -p [id]
Probrem
idが指定されなかった場合はファイル名から推測、
それでも分らなかった場合尋ねます。
:ProjectEuler -s
自分のプロファイルを表示します。
問題の箇所で
:ProjectEuler -c
現在開いている問題の言語を入れ替えます。
:ProjectEuler -o [id]
Probrem
idが指定されなかった場合はファイル名から推測、
それでも分らなかった場合尋ねます。
:ProjectEuler -u [username]
:ProjectEuler -r
現在のユーザーで強制的にログイン処理を行います。
Vimを使用中にCookieの有効期限が切れてしまった時に行って下さい。
変数一覧
g:projecteuler_user
ProjectEulerにログインするデフォルトのユーザー名
g:projecteuler_base_dir
ProjectEulerの問題およびCookieを保存するためのディレクトリ
let g:projectuler_base_dir = "path-to/projecteuler/"
みたいに設定して下さい。最後の/を忘れると正しく動作しません。
デフォルトではプラグインのおかれたディレクトリから../projecteuler/となります。
このディレクトリはあらかじめ作成する必要があります
g:projecteuler_browser_command
ProjectEulerの問題等を閲覧するブラウザ
let g:projecteuler_browser_command = "コマンド名 %URL% &"
みたいに設定して下さい
%URL%をを抜かすと正しく動作しません
デフォルトでは多分デフォルトのブラウザが起動します(ややこしい…)
g:projecteuler_audio_play_command
CAPTCHAの音声を再生するためのコマンド
let g:projecteuler_audio_play_command = "コマンド名 %AUDIO% &"
みたいに設定して下さい
%AUDIO%をを抜かすと正しく動作しません
デフォルトでは、WindowsがMediaPlayer,MacがiTunes,その他ではpaplayがあればpaplayです。
g:projecteuler_hold_cookie
ProjectEulerのCookieを保存するかどうか。
0:保存しない(Vim終了時に破棄) 1:保存する
デフォルトでは保存します
g:projecteuler_see_next
問題を正解したあと次の問題を表示するかどうか。
0:表示しない 1:表示する
デフォルトでは尋ねます
g:projecteuler_open_forum
問題を正解したあとフォーラムをブラウザで開くかどうか。
0:開かない 1:開く
デフォルトでは開きません
g:projecteuler_problem_lang
問題を取得・閲覧する際の言語を設定します。
let g:projecteuler_problem_lang = "ja"
とすれば日本語の問題文を取得・閲覧します
(日本語の問題は最初に紹介した日本語訳のページから取得しています)
デフォルトでは英語です
その他の機能
・問題のリスト表示時に、問題の説明箇所で
・プロファイル表示時に、問題の箇所で
・問題表示時に、Problem 67のようにテキストがダウンロードできる場所ではその場所で
動作の仕組みなど
音声の再生方法
ProjectEulerでは、解答の投稿にはCAPTCHA認証が必要です。ProjectEuler.vimではこれを、CAPTCHAの音声ファイルを取得して再生するという強引なやりかたで切り抜けます(あーでもこれ読むかぎりなんかいけそう)。デフォルトでは、WindowsではWindows MediaPlayer , MacではiTunesが起動しますが、これでは全然うれしくありません。Macでは、
#import <AppKit/AppKit.h> int main(int argc, char *argv[]) { if (argc < 2) return 0; NSAutoreleasePool *pool = [ [NSAutoreleasePool alloc] init]; NSSound *sound = [ [ [NSSound alloc] initWithContentsOfFile:[NSString stringWithCString: argv[1] encoding:NSUTF8StringEncoding] byReference:YES] autorelease]; if (sound) { [sound play]; while([sound isPlaying]){} } [pool release]; return 0; }
というプログラムを作って、これを
$ gcc -Wall play.m -framework AppKit -o play
みたいにコンパイルして、.vimrcに
let g:projecteuler_audio_play_command = '~/play %AUDIO% &'
とするといいと思います(参考:コマンドラインで WAV/AIFF を再生 - 空想犬猫記)。
Windowsならば、ここからplay.exeをダウンロードして、_vimrcに
let g:projecteuler_audio_play_command = 'C:\play.exe %AUDIO%'
みたいにするといいと思います。linuxなんかではpaplayがいいでしょう。こうすれば他のアプリケーションを立ち上げずにすみます。
IDの特定方法
:ProjectEuler などのコマンドでID(問題番号)を省略した場合には、現在のファイル名から推測を行います。実際には現在のファイル名から数字だけ抜き出します。つまり、Problem1.plというファイル名ならばIDは1になりますが、Problem1(2).plみたいなファイル名だとIDは12になります。予期しないIDになってしまったら素直にIDを指定してやりなおしてください。
問題の取得について
問題文はわざわざ何度も取得しても意味がないので、g:projecteuler_dirに保存します。まれに問題文が変わることがあるみたいですが、そうした場合は一度問題を消してから再び取得して下さい。
ログイン処理について
ログインはCookieで管理します。一度ログインしたユーザーは記憶されていて、それ以降Cookieの有効期限を確認せずに通信します。そのため、Vimを起動中にCookieの有効期限が切れてしまうと解答などができなくなってしまいます。もしそうなってしまったら:ProjectEuler -r で強制的にログイン処理をおこなって下さい。ちなみにprojecteuler.netのCookieの有効期限はだいたい1ヶ月です。
Cookieの削除
Cookieの削除についての設定はスクリプト読み込み時に:autocommandで設定しているのでCookieを保存したくない場合はあらかじめvimrcに
let g:projecteuler_hold_cookie = 0
としてください。
解答について
ProjectEulerでは一度問題を間違えて解答すると30秒しなければ次に解答できません。
スクリプトの文字コード
スクリプトはUTF-8で書かれています。iconvがないとWindowsでは文字化けして使いものにならなくなっちゃうとおもいます。
(2010-2-25 追記):scriptencodingというコマンドを使えば大丈夫ということなのでそれに変更しました。
問題点
・すでに解答してある問題にも解答できます。そのまま成否が判定されます(まぁでもこれはこれでいいかな)。
・Windowsではパスにスペースがあると上手く動作しないかもしれません。
・ログイン処理で「ログインに成功しました」となるのにプロファイルなどがうまく取得できなかったり問題に投稿できなかったりしたらg:projecteuler_dirが存在しないからだと思います。g:projecteuler_dirを作成してみて下さい。
vimrc
私の.vimrcは次のように設定しています。
let g:projecteuler_user = "mfumi" let g:projecteuler_audio_play_command = g:projecteuler_dir . "play %AUDIO% &" let g:projecteuler_problem_lang = "ja" nnoremap <Space>p <NOP> nnoremap <Space>pp :<C-u>ProjectEuler<CR> nnoremap <Space>pl :<C-u>projecteuler -l<CR> nnoremap <Space>ps :<C-u>ProjectEuler -s<CR> nnoremap <Space>pc :<C-u>ProjectEuler -c<CR> nnoremap <Space>po :<C-u>ProjectEuler -o<CR> nnoremap <Space>pr :<C-u>ProjectEuler -r<CR> nnoremap <Space>pu :<C-u>ProjectEuler -u<CR>
その他(感想など)
quickrun.vimと組合せれば完全にVimで完結してProjectEulerができると思います。
はじめは問題の取得しか考えていなくて、その後どんどん思いつきで機能を足していったのでコードがごちゃごちゃになってしまいました(言い訳)。特に問題文の整形処理などはいろいろと試行錯誤しながらやったのでひどいかもしれません。まぁでも自分の予想以上のものができたと思います。プラグインを作ったのは初めてだったので、いろいろなプラグインを参考にさせて頂きました。特にログイン処理はhatena.vimを、ブラウザの起動などはGist.vimを参考にしています。%とか&とかがpatternで展開されるのに気づかなかったり、'と"はいつでも同じだろうと思ったり、Windowsのパスの区切り「\」の扱いなど、結構はまりました。基本的にMacOSX SnowLeopard & MacVim-kaoriyaでしか動作確認していないのでおかしいところがまだまだあると思います。もし何かあれば、メールもしくはここにコメント頂けたら嬉しいです。