Translate

2008年7月31日木曜日

URIモジュール

URLを触る時は、URI(perlモジュール名)が超便利だと思う。

と、言うわけで触ってみた。
-分解編-
use strict;
use warnings;
use URI;

print "URI_VERSION: ", URI->VERSION, "\n\n";
my $uri = URI->new("http://www.hoge.com/path1/path2/?q1=abc&q2=cde");

print "URI: ", $uri, "\n";
print "scheme: ", $uri->scheme, "\n";
print "host: ", $uri->host, "\n";
print "path: ", $uri->path, "\n";
print "query: ", $uri->query, "\n\n";

$uri = URI->new("http://www.hoge.com/path1/path2/index.html#hoge");
print "URI: ", $uri, "\n";
print "fragment: ", $uri->fragment, "\n";

実行結果



-結合編-
use strict;
use warnings;
use URI;

my $uri = URI->new("http://www.hoge.com/path1/path2/");
$uri->query_form(q1 => 'abc', q2 => 'def');

print "URI: ", $uri, "\n";


実行結果
-------------------------------------------------------------
URI: http://www.hoge.com/path1/path2/?q1=abc&q2=def
-------------------------------------------------------------

2008年7月28日月曜日

use CGI;のタグリスト

タイトルのまんま。
よく使うのに、いまだにどのタグリストが何をサポートしてるんだかだったんで
CGI.pmよりがっつりハードコピー。

%EXPORT_TAGS = (
':html2'=>['h1'..'h6',qw/p br hr ol ul li dl dt dd menu code var strong em
tt u i b blockquote pre img a address cite samp dfn html head
base body Link nextid title meta kbd start_html end_html
input Select option comment charset escapeHTML/],
':html3'=>[qw/div table caption th td TR Tr sup Sub strike applet Param
embed basefont style span layer ilayer font frameset frame script small big Area Map/],
':html4'=>[qw/abbr acronym bdo col colgroup del fieldset iframe
ins label legend noframes noscript object optgroup Q
thead tbody tfoot/],
':netscape'=>[qw/blink fontsize center/],
':form'=>[qw/textfield textarea filefield password_field hidden checkbox checkbox_group
submit reset defaults radio_group popup_menu button autoEscape
scrolling_list image_button start_form end_form startform endform
start_multipart_form end_multipart_form isindex tmpFileName uploadInfo URL_ENCODED MULTIPART/],
':cgi'=>[qw/param upload path_info path_translated request_uri url self_url script_name
cookie Dump
raw_cookie request_method query_string Accept user_agent remote_host content_type
remote_addr referer server_name server_software server_port server_protocol virtual_port
virtual_host remote_ident auth_type http append
save_parameters restore_parameters param_fetch
remote_user user_name header redirect import_names put
Delete Delete_all url_param cgi_error/],
':ssl' => [qw/https/],
':cgi-lib' => [qw/ReadParse PrintHeader HtmlTop HtmlBot SplitParam Vars/],
':html' => [qw/:html2 :html3 :html4 :netscape/],
':standard' => [qw/:html2 :html3 :html4 :form :cgi/],
':push' => [qw/multipart_init multipart_start multipart_end multipart_final/],
':all' => [qw/:html2 :html3 :netscape :form :cgi :internal :html4/]
);

こうしてみると、パラメータのデータはCGI.pmで受け取りたいけど
HTMLはヒアドキュメントを使ってがっつりモリモリ書いてます…
という人なら
use CGI qw/:cgi/;
で、おkなのね。

パラメータをCGI.pmで受け取って、HTMLもCGI.pmで生成するのであれば
use CGI qw/:standard/;
で、おkなのね。

CGI.pmを解説しているページ
 →http://tuka.s12.xrea.com/index.xcg?p=CGI.pm

じゃんじゃん参考にさせていただきまひょ。

2008年7月20日日曜日

|| && 演算子のメモ

初期値をセットするのによく使うor演算子。
sub hoge{
my $arg = shift || "hogehoge";
print $arg, "\n";
}

上の場合は、引数があればその値を表示し
なければ"hogehoge"を表示することになる。
じゃ、下の場合は何を表示する?
use strict;
use warnings;

print 1 || 2, ",\n";
print 0 || 3, ",\n";
print "" || 4, ",\n";
print "" || "", ",\n";
print "" || 0, ",\n\n";


print 5 && 6, ",\n";
print 7 && 0, ",\n";
print 0 && 8, ",\n";
print 9 && "" && 0, ",\n";

最後に評価した物が返されるってことさえ頭にあればとくに問題ないですよね。
or演算子が最後に評価するものといえば、
一つでも真がある時、一番最初の真の値
真がない時、一番最後の偽の値

and演算子が最後に評価するものといえば
全て真の時、一番最後の真の値
偽の時、一番最初の偽の値


リファレンスの復習

用語的なもの。
リファレンス・・・値、変数を指し示す物
リファレント・・・リファレンスが指し示す元の値・変数
$scalar(変数)
$ref_scalar = \$scalar(リファレンス)
$value = ${$ref_scalar}(リファレント)

ref関数で返す値
スカラ値:undef
スカラへのリファレンス:"SCALAR"
配列へのリファレンス:"ARRAY"
ハッシュへのリファレンス:"HASH"
サブルーチンへのリファレンス:"CODE"
ファイルハンドルへのリファレンス:"IO"または"IO::Handle"
型グロブへのリファレンス:"GLOB"
事前コンパイルパターンへのリファレンス:"Regexp"
別リファレンスへのリファレンス:"REF"
bless済みの変数:クラス名

2008年7月19日土曜日

いろんなHello,World!

プログラムの最初に必ずと言って登場する言葉ですよね 笑
そんなHellow,World!突き詰めてみると案外新しい発見が
あったりするもので、なかなか侮れません 笑

そんなわけで、いろんなHellow, world!を扱った
ページでものっけておきますねぇ。

-マイコミの場合-
Hello Worldコレクション(Perlなら→Perl編 - 意外!?に多芸多才なスクリプト言語

-どう書く?orgの場合-
どう書く?org(Hello, world!)
どう書く?org(Hello, world!2)

-wikipediaの場合-
Hello worldプログラムの一覧

2008年7月14日月曜日

少し使って思った。

ここのブログ物足りないこともあるけ
ども、全般的にいい感じだーね。
ブログ単体としてみたらね。

コミュニティを含めて判断するとそれはまた別のお話だったりして 笑

動作確認用webサーバ

Catalystの動作確認用webサーバで
実行時の -rオプションは、アプリケーションが変更した時に読みなおす。
実行時の -pオプションは、ポート番号を指定。
Ctrl + c で動作確認用webサーバの停止。


-rオプションをつけずに動作確認用webサーバを起動した場合は、
アプリの変更が反映されないので、 -restartオプションをつけて
再起動する必要があるらしい。。

いろいろ試してみるか。

サブルーチン名; と &サブルーチン名; の違いのメモ。

&なしでサブルーチンを呼び出す時は、
既にサブルーチンが定義されている必要がある。
&ありの場合は、その後に定義されていても問題ない。

use strict;
use warnings;

csrf;

sub csrf{
print "こんにちはこんにちは!\n"
}

&なしのサブルーチン呼び出しだと先に定義されていないと叱られる。
定義後に&なしのサブルーチン呼び出しならOK

use strict;
use warnings;

sub csrf{
print "こんにちはこんにちは!\n"
}

csrf;

ただし、&ありでサブルーチンを呼び出すのならば
サブルーチンの定義前後関係なく呼び出しOKとなる。

use strict;
use warnings;

&csrf;

sub csrf{
print "こんにちはこんにちは!\n"
}

これだけかと思ったら、
&のあるなしで、もっともっと微妙な違いがある。
(以下、ものすごい勢いで頭の片隅において置く…)

use strict;
use warnings;

@_ = qw(abc def);

sub csrf{
@_ ? print "@_\n" : print "こんにちはこんにちは!";
}

&csrf;
csrf;


この時の &csrf; と csrf; の違いは?
ということなんですが…
ひとまず、上記コードを実行してみます。



&csrf; は、&csrf(@_);と同義。
csrf; は、 csrf();と同義。

&付きサブルーチン呼び出しは、引数を
設定していない時は、@_を渡すようです。
当然ながら、@_を設定していなければ、csrf;の時
同様こんにちはこんにちは!って表示されます。
(※と、書いてあったものの@_に何か設定することってあるのかなぁ??)

2008年7月13日日曜日

リファレンスの復習

なんだかうろ覚えなとこがあったんで
復習の意味を込めてメモ書きしておきます。

スカラーの場合。
use strict;
use wanings;

#set
my $scalar = "スカラー"; #スカラーのファニー文字は$

#リファレンス
my $ref_scalar = \$scalar; #リファレンスを取得するには\をつける

#表示
print "$ref_scalar\n"; #リファレンスを表示してみる

print "${$ref_scalar}\n"; #デリファレンスしてから表示

結果

・ひとまずまとめ。
変数や値のリファレンスを取得したい場合はそれぞれに \をつければOK
リファレンスから元の対象を参照(デリファレンス)するには、参照先の変数が
使用しているファニー文字(変数の頭につける$とか@とか)をつけるとOK
デリファレンスの書き方は、ブラケットを取り外し$$ref_scalarと書くこともOKだが…
可読性を考えると${$ref_scalara}の方がよい。


配列とハッシュの場合。
use strict;
use warnings;

#set
my @array = qw(array1 array2 array3);
my %hash = (guu => "rock",
cyoki => "scissors",
paa => "paper",
);

#リファレンス
my $ref_array = \@array;
my $ref_hash = \%hash;

#表示
print "@{$ref_array}\n";
print "%{$ref_hash}\n";

結果


さきほど、ファニー文字つけりゃリファレンス元の値を表示できると
書いてしまいましたが、配列の方は、各要素が表示されているけども
ハッシュの方は何か変ですね…
これって、
%{$ref_hash}%{リファレンス}を表示しているだけですね 汗

そもそも
print "@array\n";
で変数展開されても
print "%hash\n";
じゃ、変数展開されませんからねぇ
当然と言えば当然な挙動ですね 笑
use strict;
use warnings;

my @array = qw(array1 array2 array3);
my %hash = (guu => "rock",
cyoki => "scissors",
paa => "paper",
);
print "@array\n";
print "%hash\n";

結果


どうでもよい話ですが…
print @array, "\n";
print %hash, "\n";
とすると
array1array2array3
paarockcyokiscissorsguurock
と展開されます。。



さて横道へそれるのはここまでとして配列とハッシュの各要素を表示してみます。
use strict;
use warnings;

#set
my @array = qw(array1 array2 array3);
my %hash = (guu => "rock",
cyoki => "scissors",
paa => "paper",
);

#リファレンス
my $ref_array = \@array;
my $ref_hash = \%hash;

#表示
print "${$ref_array}[0], ${$ref_array}[1], ${$ref_array}[2]\n";
print "${$ref_hash}{guu}, ${$ref_hash}{cyoki}, ${$ref_hash}{paa}\n";

結果


配列、ハッシュ、サブルーチンは、アロー演算子を使って簡略化して表記できます。
書き方は、下記の通り。
リファレンス->[要素] 配列
リファレンス->{要素} ハッシュ
リファレンス->(引数)  サブルーチン

つまり
${$ref_array}[0]   → $ref_array->[0]
${$ref_hash}{guu} →  $ref_hash->{guu}
と書くことができる。
これって、多次元配列をデリファレンスする時に便利よいのねぇ。


ということで、次は多次元配列でも。
@number = ((1, 2, 3),
(4, 5, 6),
(7, 8, 9),
);
としたところで、多次元配列にならない。
平坦化してしまうので上の表記は、
@number = (1, 2, 3, 4, 5, 6, 7, 8, 9);
と同じことである。
多次元配列を実現したい場合は、
@row1 = (1, 2, 3);
@row2 = (4, 5, 6);
@row3 = (7, 8, 9);

@cols = (\@row1, \@row2, \@row3);

$number = \@cols;

としてあげるとOK
たとえば、4を表示するには…
${$number}[1] と書くと \@row2 というリファレンスを表している。
目的の4は、\@row2の第1要素なので…
${${$number}[1]}[0] となる。
非常にわかりづらい…
じゃ、アロー演算子を使ってもう一度考えてみる。
配列でアロー演算子を使うには
リファレンス->[要素] で表現できるので…

${$number}[1] は、 $number->[1]と表記できる
$number->[1]はリファレンスで4は、\@row2の第1要素なので
${$number->[1]}[0]となる。
${$number->[1]}[0] は、 $number->[1]->[0]と表記できる。

ちなみに、アロー演算子は ]->[  や }->{ といった風に
(角括弧|ブラケット)の間にある場合省略することができる。

というわけで、
$number->[1]->[0] は、 $number->[1][0]と表記できる。
最初に記した
${${$number}[1]}[0] と比較すると
$number->[1][0]    の方がわかりよいですよねぇ。


で、ここであることに気づきます。
せっかく、row1,row2,row3,colsという配列を作ってみたものの
最終的に各要素にアクセスするのに$number->[1][0]で済んで
しまい、せっかく悩んでつけた変数名が入ってません。
そんなわけで、無名配列を使えば変数名を使わずに同様のことができます。

配列やハッシュで値を代入する際に
@array = (1, 2, 3);
%hash = (a=>1, b=>2, c=>3);
のように括弧でくくります。
無名配列や無名ハッシュを作る場合は、
配列は[]でくくり、ハッシュは{}でくくります。
それぞれの要素にアクセスする際に何でくくるかを思い出すとよいですよね。

つまり、さきほどのrow1, row2, row3, colsを使わないで表現すると
$number = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
と表現できます。
無名配列や無名ハッシュは、"無名"なんで何かの変数に入れないと使えません。
そして、代入しているものは、実際の値ではなくリファレンスです。


次は、サブルーチンです。
use strict;
use warnings;

#set
sub csrf{ #引数を取らない場合
print "こんにちはこんにちは!\n";
}
sub message{ #引数を取る場合
my $str = shift;
print "$str\n";
}

#リファレンス
my $ref_csrf = \&csrf;
my $ref_message = \&message;

#サブルーチンを実行
&{$ref_csrf};
&{$ref_message}('今日の更新は長い…');

結果


さきほど、アロー演算子の説明の時、下記のように書きました。
リファレンス->[要素] 配列
リファレンス->{要素} ハッシュ
リファレンス->(引数)  サブルーチン

つまり、
&{$ref_message}('今日の更新は長い…');
 は、
$ref_message->('今日の更新は長い…');  と書くことができます。

ちなみに、このエントリーの最初の方でリファレンスを取得するには
変数や値に\をつければOKと書きました。

つまり、
$ref_message->('今日の更新は長い'); は、
$ref_message->(\'今日の更新は長い'); と書くことができます。

そうなると、サブルーチン内で受け取る$strはリファレンスということになるので
print関数内はデリファレンスしなければいけません。

use warnings;

#set
sub message{
my $str = shift; #$strの中身は、リファレンス
print "${$str}\n";
}

#リファレンス
my $ref_message = \&message;

#サブルーチンを実行
$ref_message->(\'今日の更新は長い…');


最後に、無名サブルーチンです。
無名(配列|ハッシュ)と一緒ですね。
my $csrf = sub {print "こんにちはこんにちは!"};
&{$csrf};
でOKですね。
無名サブルーチンは、クロージャあたりで使うらしいですよ。

strictプラグマは何でディフォルトじゃないのか?

ちらほらこの手の疑問は見かけていたものの、
自分も何でディフォルトじゃないんだろう??
と思っていました。

弾さんのブログで解説がありましたのでリンクをば。
perl - use strict なしでstrictに

2008年7月11日金曜日

予約語プログラミング

面白すぎ! 笑



TAKESAKOさんの ppencode が何で動くのか分かった。

おまけ:最もタメになる「初心者用言語」は Brainf*ck!

せっかくだから。

はてなスターを表示するコードを追加してみた。
はてなバーを入れているとディフォルトで表示されるんで
毎日ながめているとブログの方にjavascript追加して標準で
表示した方が入れてないブラウザで見る時とか便利よいかと 笑

ちなみに、はてなバー入れてるとwikipediaも☆表示されるんね
(追記)うまくいかないやん!
下記説明をもとにやってみたんですが
http://d.hatena.ne.jp/hatenastar/20070707
☆+ボタンが表示されるようになるのだけど
☆を追加すると、はてなにログインしているにも関わらず
キミにアカウントは何?おしえてーよーでれでれ
ってダイアログが表示されユーザ名を入力すると
もーログイン済みじゃん!つんつん
って叱られるんですが…


ちなみに、上記にのっけた解説ページに登場する「ははててなな」ですが…
☆+ボタンすらないですよ… 汗
http://hahatetenana.blogspot.com/

my宣言メモ

my宣言のスコープは、my宣言をしてからブラケットの終わり(})まで。
下記コードを書いた場合
$strは、ブラケットの終わりまで…
つまり、ここではif文を抜けるまでが範囲となる。
よって、if文の後に$strを書くとuse strictに
グローバル変数$strを使ってるぞ!
と、こっぴどく叱られることになる。

use strict;
use warnings;

if(1){
my $str = "ok";
}

print "$str\n"; #strictプラグマにこっぴどく叱られる



でも、同じif文でもif修飾子になるとブロックを
排除するのでスコープの範囲が変わる。
use strict;
use warnings;

my $str = "ok" if(1);
print "$str\n"; #okと表示される。

2008年7月10日木曜日

たいしたネタもないので…

ここ最近ソートに絡む記事を書いていたので
ついでに、バブルソートでも書いてみた。
(近いうちに更新する内容の仕込みです...)
use strict;
use warnings;
#bubble-sort
my $num = 20;
my @array;

for(my $i=0; $i<$num; $i++){ push @array, int(rand(100)) + 1; } print "Before-sort:@array\n"; my $loop = $num; while($loop){ for(my $i=$num-1;$i>$num-$loop-1;$i--){
($array[$i], $array[$i-1]) = ($array[$i-1], $array[$i]) if(($array[$i] - $array[$i-1])<0);

Catalyst

Catalyst…キター!



と、言うわけでCatalyst入れてみました。
あちこちwebを彷徨って見るとわかるように、GUIのppm立ち上げて
Task::Catalystを実行して、Catalystに必要な物達を入れようと企んでも
conflict forほげほげって叱られて入らないんですよねぇ。
で、-force オプションつければOKだよ!(-forceオプションは、問題がある場合でも強制的インストールするので要注意・・・)
なんて話があって、GUIの方ではオプションのつけ方がわからないので
プロンプト(CUI)の方で
ppm install -force task::catalyst でOKでした。
ちなみに、Perlのバージョンは、5.8.8。


というわけで、週末にじっくりほげほげしたりして遊んでみよう♪
参考にしたページ。
PerlのMVCフレームワーク、Catalystを試す
Perlメモ/Plaggerモジュール
ActivePerl5.8/5.PPMチュートリアル/1.PPMでモジュールをインストールする

2008年7月6日日曜日

正規表現メモ o修飾子とは

正規表現に変数を取ることができる為に
正規表現を実行するたびに内部表現へと
コンパイルが発生してしまう。

正規表現に変数(値の変わる入れ物)として使うのでなく、
正規表現を見やすくする為の置き換えとして変数を利用
している場合、リテラルと同等の為正規表現を実行する
たびにコンパイルのは無駄になる。

こういった場合、o修飾子をつけてあげると変数であっても
最初の1回しかコンパイルしないことで効率を上げるとい
った用途で使う。

どう書く?::比較しないソートの作成

どう書く?orgの問題でも解いてみました。
ひとまずこれ。
比較しないソートの作成

ソート対象のデータ同士で一切比較などを行わずにソートし、ソート結果を出力するプログラムを作成してください。条件は以下の通り。
・最低値・最大値・個数・並び替え対象の4つを引数として受け取る
・最大値と最低値はあくまで取りうる可能性であり、実際に出現することを保障するものではない。
・同値が複数出現することがある。
・入出力方法及びフォーマットは自由、関数として実装し引数に渡す形でも良い。
・小数点以下の数値が渡されることはないが、負の数は渡される可能性がある。
・最大値や最低値を元に算出した数値との比較は使用しても問題ありません。
・出来るだけ多様な条件のデータをソートできるアルゴリズムを使ってください(データが多少多いときや一定の並び順だとソート失敗するものはダメ)
・昇順降順はどちらでもかまいません

以下サンプル入出力
>>入力
-1 10 10
-1 9 4 8 9 6 3 9 5 2
>>出力
-1 2 3 4 5 6 8 9 9



ひとまず、バケットソートで解いてみました。
use strict;
use warnings;

my $set_min = -1;
my $set_max = 10;
my @set_num = (-1, 9, 4, 8, 9, 6, 3, 9, 5, 2);


&bucketSort($set_min, $set_max, \@set_num);

sub bucketSort{
my $delta = 1 - shift;
my $delta_max = $delta + shift;
my $ref_num = shift;
my @array;
for (@$ref_num){

($array[$_ + $delta]) ? $array[$_ + $delta]++ : ($array[$_ + $delta] = 1);
}
for (my $i=1; $i<$delta_max; $i++){
if($array[$i]){
my $temp = $i - $delta;
print " $temp"x$array[$i];
}
}
}

実行結果。

正規表現メモ ?:

正規表現で、javaにもjavascriptにもマッチさせたい場合
/java(script)?/と書けばよいわけだけど
括弧を使うと自動的に$1にメモリされる。

$_ = "javascript";
print "\$1=$1\n" if(/java(script)?/);


この場合
$1=script
と表示される。

でも、この手のシチュエーションで括弧内の
情報が知れると嬉しいなんてことはまずない。
つまり、使いもしないのに$1としてメモリを消費したことになる。
この無駄なメモリ消費を回避するにはどうすればよいかと言うと
最初の括弧の後に?:(クエスチョンマークとコロン)を並べるとメモリしなくなるそうな。

試してみる。
$_ = "javascript";
print "\$1=$1\n" if(/java(?:script)?/);
print "\$
1=$1\n" if(/java(script)?/);


実行結果


確かにメモリされてないですね。
コードが短けりゃ、このわずかなメモリ消費なんて気にする必要はないでしょうし
コードが長けりゃ、どこかしらに正規表現を使っていて$1等で呼び出しを一度でも
していれば、?:なんて記述はする意味がないのかなぁー
と思ってみたり。

EffectivePerlを見る限りだと相当時間にシビアな時に使うみたいですねぇ。
頭の片隅に入れときましょ。

いまさらですか 汗

会社(注)でFizzBuzzでgolfして遊んでいたら、
3の倍数と3の付く数字の時にアホになるのってどうかくのって?
話を振られたので、いまさらだけど書いてみた 笑

(/3/||$_%3==0)?print"$_(アホ)\n":print"$_\n"for(1..40);



うん。
いまさらですね 汗


(注)一応、断っておきますが、うちはメカ屋であってプログラムとは一切無縁の会社です 汗

GreyBox

0.GreyBoxって
ページを作成していて、例えばヘルプのページだったり
サムネイル状態の画像をクリックすることで本来のサイズで
閲覧したいなぁー
と言った時に便利よいのがこのライブラリ。
target="_blank"と違って、同じページ上に
灰色の透過レイヤを作成し表示してくれます。




1.download
http://orangoo.com/labs/GreyBox/Download/
内の「Download current version」の項目にあるリンクをクリック。
現在のバージョンは、5.53ですね。



2.使い方
サンプルをみるとすぐにわかります。
サンプルは…解凍後、GreyBox_v5_53内のGreyBox_v5_53をクリックし
installation.html
をクリックすると設置の仕方が書いてあります。
注)var GB_ROOT_DIR は、自分の設置するディレクトリに変えること。
後は、examplesのタブをクリックすると参考例が
のっているのでそれ通りにすると使えますね。
サンプルは、本家サイトにありますのでそちらをどうぞ。
サンプル

3.参考サイト
ゼロからはじめるGreyBox - 一歩先行くウィンドウ表示
GreyBoxリファレンス


4.GreyBoxのサイト
http://orangoo.com/labs/GreyBox/

javascript

ふと、思った。
こっちのブログでは、Perlオンリーという風に
考えていたんだけども、実際にCGI書いてたら
便利なJavascriptのライブラリも使いたくなるんだけど
CPANほど便利よいものはないので見つけたらメモしていく
ことにしました。
(だって、JSANはいまいちなんだもん。)

2008年7月5日土曜日

正規表現メモ

ちょっぴり気になったものや、間違いそうな物を
自分メモとしてまとめておくエントリーです。
ただ、ただ羅列していきますよー

・"Perl"と"Javascript"というワードの間に任意個の半角スペースまたは、タブの混在を含む文字列にマッチするには?


/Perl( |\t)+Javascript/
例)
$_ = "Perl\t\t\tJavascript"; #match!
$_ = "Perl\t \tJavascript"; #match!
$_ = "Perl Javascript"; #match!




・"Perl"と"Javascript"というワードの間に任意個の半角スペースのみかタブのみのどちらかの文字列にマッチするには?


/Perl( +|\t+)Javascript/
例)
$_ = "Perl\t\t\tJavascript"; #match!
$_ = "Perl\t \tJavascript"; #No match!
$_ = "Perl Javascript"; #match!



正規表現といえば、こちらが参照するとよいかもですね。
http://oraclesqlpuzzle.hp.infoseek.co.jp/regex/

2008年7月2日水曜日

たぶん、後で読む本。

アマゾンをふらついていて、見つけてしまった本です。
☆の評価が4.7点/5点中という人気の本なんですが
昭和29年6月25日に発行となったこの本がいまだ
人気を誇っているというのもそそられる要因だったりしたのです 笑


いかにして問題をとくか…
本書は、数学を通し未知の問題に出会った場合どのように考えたらよいかを示した本で
日常の仕事においては、未知なる問題のオンパレードです。
そういったことを踏まえても本書は、魅力的な1冊に見えてくるわけです。
今度暇があった読もう。

今読んでいる本

前の記事でも触れましたが、Effective Perlは、よか本ねぇ!
よりPerlらしく書く為の情報がてんこ盛りですばい。
ばってん。
興味ある方は、買ってみたらいかがですか~?

2008年7月1日火曜日

れっつ、そーと。

Effective Perl」面白いですねっ!
Perlクックブック」だと分厚すぎて、時間のある時に
読もうと思い持ち運びなんて使いしづらいですもんね。
その点、Effective Perlなら手ごろな厚さで内容
も濃厚で読んでいて楽しいことこの上なしです!


で、今日は14項の「数限りなきソート術を学ぼう」を読んだのですが…
変なのキター!
というわけで、これですこれkr。

@sorted_names =
 map { $_ -> [0] }
 sort { $a -> [1] <=> $b -> [1] }
 map { [$_, -M] } @files;

@filesに格納されているファイル名をファイル変更日付でソートかけてるわけです。
これだけだと何のことだかわけわかめなんで、順を追ってメモメモ。


まずは、sort関数と言うと…下記の通りですよね。
ソートされた関数 = sort (ソート順の定義)? ソート対象のリスト;

use strict;
use warnings;

my @before = qw(e c a d b);
my @after = sort @before;
print "@after\n"; #a b c d e


じゃ、数字をsortしようとすると…
use strict;
use warnings;

my @before = 1..10;
my @after = sort @before;
print "@after\n"; #1 10 2 3 4 5 6 7 8 9

もし、ASCII順に並べ替えたいのならばこれでよいですが
たいていの場合この結果を期待する人は少ないはずですよね 汗
そうなると次に登場するのがソートの定義です。
さきほどの、数字の並び替えを期待したとおりに行うには下記のように
スペースシップ演算子を使って数値的にソートを行う必要がありますね。
use strict;
use warnings;

my @before = 1..10;
my @after = sort { $a <=> $b } @before;
print "@after\n"; #1 2 3 4 5 6 7 8 9 10

今度は、期待した通りになりましたね!
では、最初のファイルを更新日順にソートする話に戻ります。
簡単に書くのであれば
use strict;
use warnings;

my @files = qw(file1.txt file2.txt file3.txt);
my @sorted = sort { -M $a <=> -M $b } @files;
print "@sorted\n";


一般的に、比較をベースとするソートアルゴリズムは、
1回のソートでn log n回(nはソートする要素数)と言われているそうです。
つまり、単純な数値比較だとn log n回の数値比較を行うのに対し
ファイルの更新日順に並べるソートの場合、n log n回分の
ファイル更新時間の取得とその比較を行っている為無駄の
多いソートになっているわけです。

例えば、初めて比較する時だけファイル更新時間の取得を行い
それをキャッシュしておき、2回目以降の比較の際はキャッシュを
参照した方が高速になります。
要は、n log n回分の比較と n回分のファイル更新時間の取得で済むので。
それをあらわしたコードが下記のようになります。
use strict;
use warnings;

my @files = qw(file1.txt file2.txt file3.txt);
my %m;
my @sorted = sort {
($m{$a} ||= -M $a) <=>
($m{$b} ||= -M $b)
} @files;
print "@sorted\n";

ちなみに、 $m{$a} ||= -M $a は、
$a = $a + 10; の省略形が $a += 10; となるのと同様に
$m{$a} = $m{$a} || -M $a; が $m{$a} ||= -M $a;
と、なっているだけです。


で、上の内容をPerlハカーな方々は、シュウォーツ変換を
活用して書くそうでそれが、一番最初に出てきたコードだったわけです。
本によると、シュウォーツ変換とは、mapで囲まれたsortである(?)となってます。

キューピー3分●ッキング♪
本日の●ッキングは、3つのファイルを更新順にソート致します。
まずは、材料を用意します。
今回は、my @names = qw(file1.txt file2.txt file3.txt);を使います。
まずは、ソートの条件を確認します。
比較対象→ファイル更新日
アウトプット→ファイル名
と、言うことでまずは、下準備から。
では、mapで名無しリストを作成します。

@names_and_ages
= map { [$_, -M] } @names;

この時、@names_and_agesの各要素には、[$_, -M]という
ファイル名と更新日時の無名リストのリファレンスが格納されます。
@names_and_ages = [["file1.txt", file1.txtの更新日],
                ["file2.txt", file2.txtの更新日],
                ["file3.txt", file3.txtの更新日]
               ];
こんな感じですね。
次が、この○ッキングのメインのソートです。

@sorted_names_and_ages
= sort {
 $a->[1] <=> $b->[1]
} @names_and_ages;

$a <=> $bだと、リファレンスの比較になっちゃいますね 汗
比較したのは、更新日なので、リファレンスの第2要素を指定する為
$a->[1] <=> $b->[1]となってます。

調理が完成したら、@sorted_namesという皿に盛り付けるだけです!
@sorted_names = map { $_->[0] } @sorted_names_and_ages;

@sorted_names_and_agesには、更新日を元にリファレンスが並び替えられてます。
最終的に欲しいデータは、ファイル名なので…
ファイル名は、リファレンスの第1要素に格納されているので
mapで$_->[0]を抜き出してリストを作って完成っと。
同じ変数を代入していくと…
use strict;
use warnings;

my @files = qw(file1.txt file2.txt file3.txt);
my @sorted_names =
map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [$_, -M] }
@files;
print "@sorted_names\n";


完成です\(^o^)/
とっても、おいしい料理ができあがりましたね!!


では、もう一度本日のおさらいです。
1.並び変えるデータ並び変え判定に使うデータのリファレンスを作成。(map)
2.並び変え判定に使うデータで並び替え。(sort)
3.並び変えるデータ並び替え判定に使うデータから並び替えるデータを取り出す。(map)
以上!

で、sort関係に関連してネットをさまよっていたら楽しい
ページをいくつか見つけたのでメモ書きしておきますね。
あなたが一番好きなアルゴリズムを教えてください。
また、その理由やどんな点が好きなのかも教えてください。

はてなの質問です。
個人的にはエラトステネスの篩が好きです 笑


プログラマーでなくても名前ぐらい覚えておきたいアルゴリズムx10
弾さんの記事です。
こういう記事を見ない限りなかなかアルゴリズムの知識も
増えないので非常に為になりました。。

最後は、
いろいろなソートアルゴリズム
バブルソート/バケットソート/基数ソート/ヒープソート/マージソート/クイックソート
をJavaアプレットを駆使してわかりやすく解説してあります。
昔、おもれーって思って何度も眺めていた記憶が 笑

Project Euler.net

で、前フリを済ませたとこで…
さすがに、ランキング形式になている以上
解答のコードをのっけるわけにはいかないので
参考までに、
マシーンスペックと解答にかかった時間でものっけときますね。
(無駄の多いコード書くと途方に暮れてしまう場合がありますしねぇ 笑)

※測定に使っているノートPC。
OS:Microsoft Windows XP Professional Version2002 SP2
CPU:Intel® Core™2 Duo 2GHz
メモリ:1GB RAM
Perl 5.8.8
(※1 スペックが高いマシーンだと差が出ないのでノートでチェックしてます)
(※2 Time::HiResモジュール使用)


Problem 1  0.001秒
Problem 2  0.000秒
Problem 3  0.003秒
Problem 4  0.042秒
Problem 5  0.057秒
Problem 6  0.001秒
Problem 7  16.516秒
Problem 8  0.004秒
Problem 9  9.391秒

Ploblem (7|9)は、もう少しコードの見直しをする余地がありそうですねぇ...
Ploblem 3の600851475143の素因数のうち最大の値は?
って問題は、純粋にエラトステネスの篩を使ってみたところ
3時間2分44秒もかかってしまいましたからねぇ 笑
いかに無駄を無く書くかってのが大事かってのが身にしみました…

現在215番目/310人中

Project Euler.net

最初の投稿だけながながと。
Project Eulerとは…
以下サイトより拝借(別名引用)[引用先:http://projecteuler.net/]
----------------------------------------------------------------------
What is Project Euler?
Project Euler is a series of challenging mathematical/computer
programming problems that will require more than just mathematical
insights to solve. Although mathematics will help you arrive at
elegant and efficient methods, the use of a computer and programming
skills will be required to solve most problems.
----------------------------------------------------------------------

個人的主観を交えた意訳をするとProject Eulerってサイトは、
コンピュータを必要とするような大きな桁の数学の問題を
みんなで解いてランキングしようぜ!ってお話。(マテ
http://projecteuler.net/

で、好きな言語で問題を解いて各問題のページには
回答用のフォームが用意してあるので回答を入力して
送信することで正誤のチェックをしてもらえます。
その正誤を元にランキングが作られているってわけ。
ランキングは、Top1000 Scorers国別のランキング言語別のランキングがあります。
回答だけ書けばよいので、その気になれば手計算でもよいし!
BFだろうがWhitespaceだろうがちょっと草植えときますね型言語
であろうが何でもOKですね!

問題に正解すると、正解者だけが見ることのできる
フォーラムへ移動することが可能になります。
フォーラムには、コードをのっけている人もいれば
コメントだけの人もいます。

今日現在(2008/07/01)。
お題は、200問に到達。少しずつ増えてます!

興味ある人は、登録してめきめき解いてみたらいかがでしょうか?
問題文の日本語訳は、こちらにまとまってます。→こちら