2桁増やせば自動で直してくれる難しい式

例えば、振込の時口座番号を間違えて打ち込んだと。
照会できる場合は、打ち間違えても大概そんな口座ないよと言ってくれる。
チェックディジットのおかげですね。1文字なら間違えてもそんな口座ないから大丈夫ということ。
とはいえ、照会できなければ気付かないまま振り込んでしまうことになる。
すると振込手数料は無駄になるし、組戻手数料を取られることもある。
しかし多少の間違えなら自動で訂正してくれたら便利ですよね。


そんな銀行は聞いたことないが、不可能ってことはないですよ。
数学の力を借りればなんとでも。
こういうのを実現する方法はたくさんあるのですが、
まぁ有名なのはハミング符号ですよね。
調べると4ビットのデータに3ビット加えて7ビットにすれば、
1ビットの誤りを訂正できると。
ただその程度ということです。そんなにすごい能力が高いわけでもない。
メモリのデータの検査に使われていますよ。
64ビットを単位にして、8ビット加えて、1ビットの誤りを訂正できる。
こういうのをECC対応メモリ言うんだけどね。まぁPCでは使われないですね。サーバー向けね。
ただこれがさっきの目的を達成するのに向いてるわけはないわな。
人間が間違えるんだから1ビット単位で間違えるわけじゃないよね。
文字単位で間違えますからねー、これはダメです。
じゃあと発見したのが、リード・ソロモン符号というやつ。RS符号と略するらしい。
これは2rのシンボルを単位としてやるのだが、
シンボルの中でどう間違えようと1つの間違えとしかカウントされない。
なので何文字か打ち間違えても補正がきくという仕組みにはもってこい。
けど難しすぎる…リード・ソロモン符号 (Wikipedia)見ても難しすぎ。


まぁしかしいろいろ調べてるとわかることもある。
RS符号は8桁のデータに、2桁の符号を加えるとかいう風にして作ると。
これで加えるのが2桁なら1文字、4桁なら2文字の補正がきく。
それを超えると補正失敗するか間違いを増やす補正をやるかどっちか。
それで桁数制限がありまして、2r個のシンボルを使うなら、合計2r桁までしか無理。
初め、10進数の範囲で入力できるように0~7の23個のシンボルを使おうと思ったのだが、
すると7桁までしか無理だと。2r桁未満ということ。
1桁補正するためには2桁は訂正用に使うから、データは5桁までしかいけない。
しかも8進数の5桁だから、たった32768個にしか対応できない。
これでも実用的かもしれないけど、なんというか。
というわけで今回は0~9、A~XのうちIとOを除いた32文字を使って、
6桁のデータに2桁付加することにしよう。
これならおよそ10.7億個分も用意できる。
無尽蔵とは言えないけど、31桁までは増やせるんだからね。


さて、その前にRS符号では有限体とかいうやつを使うらしい。
フェルマーの最終定理の証明にも使われた代物だとか。
0~31の範囲で加減乗除しても0~31の範囲に戻ってくるものということらしい。
この有限体の世界でいろいろやるらしい。意味不明ですね。
足し算は排他的論理和を使えばいいらしい。引き算も排他的論理和だと。
だからこの世界では31+7は24だということ。
CとかPerlでは排他的論理和は^の演算子を使うから、31^7=24と書けばよいか。
しかし^という記号はべき乗を思い浮かべるからどうも…
かけ算だが、αnで1~31までの値を表せるようにして、指数法則で計算しろと。
αというのはなんかわからんけどこの世界のべき乗で1~31の数字を用意できるものということ。
それで、どうもこれを作れるのが素数個のときと、素数のべき乗個のときらしい。
なので10進数でRS符号は作れないと。11進数とか9進数ならできるみたいだけど。
これなんだが、さっき書いたWikipediaの記事にいろいろ書いてあるが、
まずα0=1、α1=2、α2=4、α3=8、α4=16と。
ここまではそういうものらしい。ここからが問題。
ここで原始多項式という魔法のような式を使ってやる。
それ以下の次数の式では割り切れない式というやつで、その性質があればいいらしい。
擬似ランダムパターン発生回路のページの下の方に載ってますね。
まぁこれの5次の式を持ってくる。x5+x2+1って式ですね。
これを変形して、+をこの世界の足し算である^に置き換えて、xにαを代入して…
α5=α2 ^ 1 = 5
これ以上だが、これを両辺α倍して…とやっていくので…
α5+n=α2+n ^ αn
の式のnを増やしながら計算すればいいんじゃないかな。これでα0からα30の値をGET!
ちなみにα31=α0=0です。まぁ一周回ってくるということ。
しかし手作業でやるのもめんどくさいので、$a[$n]がα$nの値になる@aをPerlで作ってみた。

@a=(1,2,4,8,16);
$a[5+$_]=$a[2+$_]^$a[$_] for(0..30-5);

結果なんだが、
@a=(1,2,4,8,16 , 5,10,20,13,26 , 17,7,14,28,29 , 31,27,19,3,6 , 12,24,21,15,30 , 25,23,11,22,9 , 18)
となる。これを使えばこの世界のかけ算・わり算ができる。
10×7は、10がα6、7がα11なので、指数法則で答えはα17=19と。
わり算も10÷7=α-5=α26=23となるわけ。
実はここまでたどり着くのが一番大変だった。


Perlで符号化と復号化するから使う計算を用意するね。
$xを@aの中の何番目か探すのは実はlogα($x)なのでloga関数として用意。

sub loga{
for(0..$#a){
return $_ if($a[$_]==$_[0]);
}
return undef;
}

当てはまらなければundefを返す。0はないからundefが返ってくる。
α$nを$a[$n]と書くのはかっこわるい気がしたからapow関数として用意。

sub apow{
return $a[ $_[0] % 31 ];
}

31で割ったあまりを取るのがポイントです。apow(-5)とすれば$a[26]を取ってくれるんですね。
これを使えばかけ算・わり算・べき乗も簡単ですね。

sub mul{
my $p=0;
for(@_){
my $c=loga($_);
return 0 if(!defined $c);
$p+=$c;
}
return apow($p);
}

かけ算のポイントだが、0だとloga(0)はundefが返ってくる。undefが返ってきたらその瞬間0が答えになると言うこと。
0に何をかけても0なのはこの世界でも変わりません。
mul(2,3,4)とすれば2×3×4ということね。まぁあんまり意味はないけど。

sub div{
my $p=loga($_[0]);
return 0 if(!defined $p);
my $c=loga($_[1]);
return undef if(!defined $c);
$p-=$c;
return apow($p);
}

分子に0が来たらundefを返すようにしてる。分母が0なら0なのは当然ですね。

sub pow{
return apow(loga($_[0])*$_[1]);
}

これはそのままですね。こんな風にlogを使って計算する世界だということです。
この世界での計算はこれと排他的論理和だけあれば十分です。


これでやっと符号化に入れる。@aを作って、計算を定義して、やっとですね。
@i=(1,2,3,4,5,6)を符号化します。
で符号化の理屈ですが、2桁加えるときは、
G(x)=(x ^ α0)(x ^ α1)
というxの式を用意します。2桁だから2つの項ね。4つならαの指数を増やして用意するだけ。
Perlでスクリプト書いて展開させてもよいが…めんどくさいから手でやろう。
G(x)=x2 ^ (α0 ^ α1)x ^ α1
分配法則使って展開すればいいのね。
で、整理すると x2 ^ 3x ^ 2となる。@g=(1,3,2)として格納しておこう。
参考までにスクリプト@gを自動生成するスクリプト。

@g=(1);
for my $i(0..2-1){
my $a=$a[$i];
unshift @g,0;
$g[$_]=($g[$_+1]//0)^mul($g[$_],$a) for(0..$#g);
}

筆算してるみたいなもんですよ。4桁とかなるとこれないと大変ですので。
この式を生成多項式というらしい。これは32個のシンボルを使って、2桁付加するときは共通。
さっきの@iに付加する2桁を加えて、こんな多項式を作る。
C(x)=1x6 ^ 2x7 ^ 3x5 ^ 4x4 ^ 5x3 ^ 6x2 ^ Px ^ Qというxの式で表したもの。
これをG(x)で割り切れるようにすればよいと。結局の所、
1x6 ^ 2x7 ^ 3x5 ^ 4x4 ^ 5x3 ^ 6x2をG(x)で割ったあまりがPx ^ Qになると。
めんどくさいですねー。一体誰がこんなのを考えたんだ。
とりあえずさっきの式を@p=(1,2,3,4,5,6,0,0)と表して、@gで表してG(x)で割りましょうか。

while(@p>=@g){
my $r=div(@p[$#p] , $g[0]);
$p[$_] ^= mul($g[$_],$r) for(1..$#g);
shift @p;
}

多項式のわり算ってのは、わる式よりも次数が余りの次数が低くなるまでやるもんだ。
例えば、(2x+2)÷(x+2)は商が2で、余りが-4、これは2x+2=2(x+2)-2で式が表されると言うこと。
それでこの処理で残った@pが余りと。(13,10)が残る。
というわけでさっきの式のPには13が、Qには10が当てはまる。
これで完成。
あとは初めに書いた32進数の文字に当てはめると。
1,2,3,4,5,6は数字そのまま、10はA、13はDですね。
文字リストを@cに入れて、$c[$n]とやって取り出すと便利ですよね。
というわけで結果は123456DAとなると。これで1文字間違えても訂正できるデータできあがり。


作るだけでこんなにめんどくさいのに、訂正なんてもっとめんどくさい。
受け取った方は、これを多項式にする。
C(x)=1x6 ^ 2x7 ^ 3x5 ^ 4x4 ^ 5x3 ^ 6x2 ^ 10x ^ 13
それでシンドロームというものを求める。
2個文字を加えたなら2個のシンドロームができて、
それはS1=C(α0)、S1=C(α1)、なんと代入するんですね。
まぁめんどくさいわ。さっきの多項式は@rに(1,2,3,4,5,6,10,13)と格納することにしよう。

@s=();
for my $n(0..2-1){
my $s=0;
for(0..$#r){
$s^=mul($r[$_],pow($a[$n] , $#r-$_ ));
}
push @s,$s;
}

これでシンドロームの配列@sが作れた。結果だが(0,0)となる。
実は成功していれば全部の値が0になる。なぜならばC(x)はG(x)で割り切れて、
G(x)は式の形をみてもわかるように、xにα0 と α1を入れたら0になる。
だからC(x)にそれを入れても0となると。ならなければ間違えです。
それで訂正方法だが、Wikipediaの記事を見るとけったいな行列式が書いてある。
けど1文字しか訂正しないならいろんな式が簡単になって、
1 ^ (S1S2)αn=0を満たすnを発見すればよいと。
変形して、αn=S1/S2、
対数を取って、n=logα(S1)-logα(S2)、
$n=loga($s[0])-loga($a[2]) となるわけですね。
そして、x31-$nの項を修正する。(-$n)%31を取るといいと思います。
修正方法はS1の値を足す、だから排他的論理和を取るだけ。
例、@r=(1,2,3,4,5,6,10,13)を@r=(1,2,3,0,5,6,10,13)と入力されてしまった。
すると@s=(4,10)となる。これより$nを計算すると-4となる。
だからx4の項、だから$r[$#r-4]の項ですね。
現在の値は0だけど、これを$r[$#r-4] ^= $s[0]と修正する。
すれば@r=(1,2,3,4,5,6,10,13)に訂正できた。めでたしめでたし。


と、わけのわからない計算ばっかりしてきましたが、
これをPerlで作っていろいろやってみるとなかなか楽しいです。
ちょっと打ち間違えてみても、直ってしまうんですね。
これで2個訂正可能にしたいんですが、訂正の式が難しすぎるので…
まぁいろいろ試してみようかなと思います。
うっかりミスを修復できれば何かと便利だよなーとは思いますけどね。
しかしえらいものがあるもんだ。こんなにすごいものが世の中にあったとは。
難解だし、計算しにくいけど、すごい強力だな。

寒くて、珍しく雪が降って、夏は暑いところ

今日は雪が降った。結構珍しい。
というのも、この時期はそもそも雨が降ることが少ないんですね。
昨日は雨が降りましたけど、大体そういう日は暖かいんですね。
夜に雲がいると、熱が逃げない。なので気温が3度ぐらいにしかならない。
非常に暖かいです。普段は氷点下1度とか2度なのにね。
けど今日はそれにしては寒くて、アメダスで見るに1度ぐらい。
氷の粒みたいな雪が降ってきてますね。


さて、気になってうちに近い観測所の平年値を使って雨温図を書いてみた。
平年値については過去の気象データ検索 (気象庁)を使って調べるといい。
さて、降水量だがちょっと少ない。年間で1400mmぐらい。そんなに極端じゃないけどね。
まぁ例によってこれを梅雨と台風でけっこう稼いでるわけでねぇ。
それで冬はあんまり降らないと。まぁそんなところです。
気温だが平均気温は14度ぐらいだから、暖かくはなさそうだな。
とはいっても冬が平均気温3度ぐらい、夏が平均気温26度ぐらい。
冬は毛糸の帽子かぶって、上着着て、手袋はめないと自転車でまともに走れない。
夏は昼に歩いてると、汗が…まぁ夏はそんなもんだと思うけど、冬がひどい。
だから平均気温が低いんですよ。
まぁそれはそうと、この雨温図を見せられて、どの気候区分に入れるかは難しいですよね。
雨少ないから、中央高地の気候か瀬戸内の気候かどっちかかなと。
それでそんなに寒くはないから、瀬戸内の気候と答えればいいかなと。
しかし残念ながら、うちは中央高地でないのは明らかだし、瀬戸内海に面しているわけでもない。
一体どうなんでしょうねぇ。別に生活する分には関係ないですけどね。


さっきまで、雪降らないといいましたが、
実は年に1回か2回ぐらい恐ろしい雪の降る日があるんです。
雪への備えもあんまりなさそうなところなら、恐ろしい事になるだろう。
と思うのですが、幹線道路は融雪剤撒いたのかシャーベット状になってるのね。
近鉄は滅多に運行見合わせにならないので、案外問題ないんですね。
というか雪が降ってもその程度だということです。タイヤに付けるチェーンなんて持ってないよ。
まぁバスはたまにつけてるみたいだけど。
とはいえ、自転車が使いにくいから駅まで歩かなきゃいけませんけどね。
シャーベットの上を走るのは怖いですから。
今年もそんな日はあるんじゃないかなと思うのですが、
それに動じず安全にいきたいものです。

小字に郵便番号は阻まれる

だいぶ前の話になるのだが、住所の整理をしていたと。
その成果により年賀状を送れたわけですが。
友人に宇治市と京田辺市に住んでる人がそれぞれ1人はいた。
それで郵便番号がないので、郵便事業のOHPで調べたわけだ。
普通はこんな風に調べる。
奈良県大和郡山市北郡山町248-4とあれば、
奈良県を選んで大和郡山市北郡山町と入れる。
すると容易に639-1160というのが得られる。本当に便利な世の中です。


ただ、郵便番号の節約のためか、都合の悪いこともある。
例えば大阪市浪速区日本橋三丁目とか調べてもヒットしない。
N丁目などは外して登録されていることが多いようなので、
外してヒットすればOKだと。556-0005と書けばいいですね。
しかしこういう風に行かなかったのが、宇治の人と田辺の人だ。
京都府宇治市宇治琵琶33という住所を言われたと。
ところがヒットしない。あれ?と思って市町村全部の一覧から調べたと。
すると宇治というのがあると。
まぁしゃあないのでこれを書いておいたと。611-0021ですね。
結論から言えば正しかったのですが、どうも気分が悪い。


最近その原因を知ったのだが、どうもこの琵琶というのは小字らしい。
小字と言えば、中村字大谷1345番地2 とかいう表示の字大谷の部分ですね。
こんなの別にどうでもいいですよね。と僕は思ってたけどね。
こういうのは中村1345-2と書けば届きますからね。
しかし、実際は小字が違えば同じ番地がある地域があるらしい。
実は宇治市はそうらしい。なので、小字も忘れず書きましょうと。
郵便番号は町名からN丁目などを取り除いたものに1つ与えられるのが基本。
それで宇治という町名に対して611-0021を振ったと。
けど直感的じゃないですよね。宇治琵琶という名前の町名にしか見えないし。


田辺の人も同じようなことが起きまして、
まぁ郵便番号を探して書いておいたと。
それでどこに住んでるのかなと思って、地図を調べたと。
すると、興戸犬伏、興戸八木屋、興戸塚ノ本…とそんなのがひたすら並んでる。
どんな風になってるかは、Yahoo!地図で見ればいいと思います。
まぁ目が痛いわ。
ところが状況としては似てそうな宇治市は宇治とかいう町がただあるだけ。
うーん…家の場所なんてわかったもんじゃないよね。
ただし住所データには入ってるので検索すれば出てきますけどね。


まぁあんまり気にしないことにはしたけど、
感覚と郵便番号と地図の表示は違うなぁと思ってね。
それ以外はそんなに問題なく出せたんだけどね。
それにしても小字か…
郵便番号って目標は郵便番号と数字で住所を全部表示できることだとか。
大阪府大阪市浪速区日本橋三丁目6番22号なら、
5560005-3-6-22という風に。これでカスタマーバーコードを生成します。
けど、京都府宇治市宇治琵琶33は無理ですよね。
6110021-33となるけど、これで琵琶という情報が飛ぶから。
これは手動でしか分けれませんよね。
まぁ実はこの目標は達成できているというわけでもないようです。
まじめに番号を振ったら番号がパンクするのかなと想像しておこう。

Base64をデコードしてたらWindowsに邪魔された

実験データをZIPで固めて、メールで送ってもらったのだが、
受信に失敗したので再送してもらおうと思ったが、今度は送信でこけた。
元ファイルは今手元にないのだが、過去に送ったメールはメールソフトに残ってる。
というわけでこれを探して、メールのソースをアップロード。
これでデータは家で取ることが出来た。けどBase64でエンコードされてる。さあどうする。


こういうときにPerlを使うんですね。
まぁBase64のデコードはMIME::Base64のdecode_base64関数でやればよいと。
なんてことないですね。

use strict;
use warnings;
use MIME::Base64;
open my $if,'<','in.txt';
my $b='';
$b.=$_ while(<$if>);
close $if;
open my $of,'>','out.zip';
print $of decode_base64($b);
close $of;

非常にわかりやすいプログラムですね。
たまには決まり文句も書きましょうか。
in.txtを開いて、1行ずつ読んで、これをどんどんくっつけて$sを作る。
まぁ多分これでOKだと思います。
ReadToEndメソッドみたいなのは、確かなかったはずだし。
それで$sを全部decode_base64でデコードする。
ここで1行ずつ読み込んではデコードして書き込んでも多分OK。
ただBase64は4文字セットで処理しないといけないのだが、
改行の位置がおかしいと1行が4文字単位になってないことがある。
なので一応全部読み込んでから処理するようにしてる。
しかし!ファイルが破損していると出る。


実は、これはLinuxでコマンドラインで使う1行プログラムを参考に作った。

$ perl -MMIME::Base64 -e "print decode_base64($_) while(<>)" < in.txt >out.zip

-MXXXはuse XXX;に相当するかな。XXXというパッケージを読み込むと。
リダイレクトで標準入力から入力ファイルを入れて、
標準出力に出したやつをリダイレクトで出力ファイルに出す。
結構Linuxとかでは使います。便利です。
しかしWindowsでこの方法が通用しないのはもう何度も体験している。
というのも、Windowsでは入出力全般で、入力時CR+LFとなっているものはLFのみに変換され、
出力時LFはCR+LFに変換される。というなんかよくわからない機能が付いていると。
これが結構困るんですね。それでさっきの1行プログラムはその辺考えてないと。
そういう事実にはすぐ気付いたのだが、自分でプログラム書いたらそれを忘れてたと。

binmode $of;

これで$ofをバイナリモードにすると。
これを$ofを開いた後に入れればOKです。めでたしめでたしと。
ちなみにさっきの1行プログラム、いろいろ試してたがこうすればWindowsでも動く。

perl -MMIME::Base64 -e "binmode STDOUT; print decode_base64($_) while(<>)" < in.txt >out.zip

まぁSTDOUTをバイナリモードにしておけば問題ないですね。


Linuxではこれを気にせずに、バイナリを流せるんですけどね。

$ tar cvf - foo/ | bzip2 -c | uuencode  foo.tar.bz2 | mail hidemaro

まぁこんな具合にバイナリだろうがテキストだろうが、パイプを行き交うと。
最近では使いませんけど、昔はtarで標準出力に出したり標準入力から読んだりと、
そういうときはファイル名のところに-を当てはめればよろしいと。
これをすればfoo/をtar.bz2で固めてメールで送ってくれる。
Windowsではこんなことしませんよね。
僕はパイプ名人でもないけど、コマンドを通して処理するとかいうのは、
結構便利だからWindowsでも活用したいなと思うけど結構難しい。
以前それがためにCygwinを入れてたけど、再インストールの時に入れなかったからね。
最近は結構Perlでできることが多いことに気付いて、
自作したperlshで、試行錯誤しながら、CPANも活用しつつやってます。
そっちの方が柔軟にできるのでね。
今更どうにもならないけど、もっとパイプが使いやすい仕様ならなと思わないこともない。

金は足らない、けどスポンサーの下で商売は続けるよ

去年の末に民事再生手続開始の申立をした九十九電機が、
ヤマダ電機の新しく作る子会社に事業譲渡することで合意したと。
まぁちょっと不思議な話ではありますけどね。
まだ再生計画の認可を受けてないんですよね。
民事再生法というのは、借金の金額がやたら多い、けど事業を続けることはできる、
という会社を助けるために、借金の一部を免除とかできるようにする法律です。
聞けば、九十九電機は黒字だったらしいです。過去に借金を作りすぎたという事情があったと。
だからこの制度を使うことができるんですね。
どのように経営していって、どんな風に借金を返すかということを計画して、
これを裁判所に出して認可してもらわないといけないと。そういうことです。
ところがこの計画を出す前に事業を別の会社に移すと。


実はこういうことは結構あるらしいです。
というのも借金だらけの会社だと商売しにくくなるから、
価値が下がる前に新しい会社に事業を移してしまって、そっちは元気にやっていってもらうと。
残った会社の方は借金の返済に専念すると。
事業譲渡のときにお金が入ってくるから、このお金でも返済できますしね。
そういう再生もあるそうです。再生なのかはよくわかりませんけど。


まぁツクモは、何かとマニアからの評判がよくて、
一時、担保にしてた商品が回収された後、商品を仕入れ直して営業を再開したとき、
結構買ってくれる人が多かったと。ありがたい話ですね。
僕も、今のPCの構築に、ツクモから通販で部品を買いましたからね。
通販での品揃えがかなりいいですし、値段も悪くはない。
そんなわけでたまにツクモの通販で買うことはあると。
まぁ実店舗も品揃えいいから使うことあるけど、そちらは部品ごとにバラバラに買うこともあるしね。
そんなわけで、再生に向けてがんばっていただきたいなと。
ユーザーとかスポンサーが支えてくれれば、多分成功するんじゃないかなと思いますよ。
僕は専門家じゃないから実のところどうか知らないけど。

もしも文字列に式を埋め込めたならば

素数をたくさん求めたいなぁと思って、Perlでこう書いてみた。

@p=(2);
my $n=3;
while(@p<10000){
my $l=sqrt($n);
for(@p){
last if($n%$_==0);
if($_>=$l){
push @p,$n; last;
}
}
$n++;
}

エラトステネスのふるいを使ってるんですよね。
$nが素数であるか確かめるには、sqrt($n)未満の素数で割り切れないか確かめればよいと。
そこまで割り切れることなくたどり着けば@pにpushされると。
最近のPCは高性能だからこんなのも一瞬で計算できますよ。
ちなみに10000番目の素数は104729でした。


以前から気になってたのだが、Rubyではこんなことができる。

puts "料金は#{ (p*1.05).round }円です"

普通、#{i}のように変数名を入れて使いますけど、
どうも式を入れてもOKらしいです。結構便利ですね。
ちなみにPerlには四捨五入するいい関数ってないんですよね。
強いて言えばint関数だけど、int関数は実は結構ひどい関数なんですよね。

print int( (0.725/0.05)+0.5 ),"\n";

0.725/0.05は14.5になるはず。四捨五入すれば15ですね。
四捨五入の時0.5加えて、小数点以下を切ればいいと。
だけど実際はそうはならない。有限桁の10進小数も、コンピュータ内部で使う2進数にすれば無限小数になることあるから。
そのときに微妙に誤差が発生して、14.9999999…となってるのね。
これで小数点以下を切り捨てると14ですよね。まぁこういう都合があると。
で、どうも調べると、CPANからMath::Roundモジュールを入れろと。

perl -MCPAN -e "install Math::Round"
ppm install Math::Round

普通は上の方法でOKだと思うんだが、ActivePerlではなぜか知らんが失敗する。
ppmコマンド使えばいいんだが、ppmで何でも入るわけではないし…
まぁこれなら賢くやってくれますねと。
それでやっとさっきのRubyのプログラムと同じ事が出来て、

print "料金は",round ($p*1.05),"円です\n";

こんな風になると。
round関数がMath::Roundの四捨五入。他にもいろいろあるけどね。


さて、ここからが本題で、Rubyでは#{ }内に式を入れることができた。
けどPerlでは”本体価格は$p円です”のように変数を入れることはできても、式はできない。
まぁそんなもんかと思ってたのだが、こんな方法でできるというのを見た。

print "料金は@{[ round ($p*1.05) ]}円です\n";

#{ }同様のことが、Perlでは@{[ ]}でできると。
一体これは何のことかというと、[ round ($p*1.05) ]という配列リファレンスの指す配列を表示していると。
これは知らなかったのだが、実は配列も”配列の中身は@aである”のように書けば展開されると。
$aという配列リファレンスの指す配列も@$aとか書けば展開されると。
そして配列リファレンスは[ ]で直接用意することができる。
@[ 1,2,3 ]などでは何のことかわからないので、@{ [ 1,2,3 ] }とすれば配列に戻せる。
そしてこういう表記で””内に埋め込めばいいと。
えらいもんですねー。まさかこんな仕掛けがあるとは。
そういう仕掛けなので、@aの要素数を埋め込みたいからといって、”@{[ @a ]}個の要素があります”など書くと、
[@a]は@aと同じ要素を持った配列のリファレンスになってしまうから、@aの中身がでてしまう。
なので、@{[ scalar(@a) ]}とか、@{[ @a+0 ]}とかを埋め込むようにしないといけない。


奇妙な仕組みですが、便利かも知れませんねぇ。
例えばヒアドキュメント内部で使うとか。

my @clock=localtime();
print <<"EOF";
本日は@{[ $clock[5]+1900 ]}年@{[ $clock[4]+1 ]}月$clock[3]日(@{[ qw(日 月 火 水 木 金 土)[ $clock[6] ] ]}曜日)です。
ただいまの時刻は$clock[2]時$clock[1]分$clock[0]秒です。
EOF

実はlocaltime関数の結果は結構取り扱いめんどくさいのよね。
年は1900足さないとだめだし、月も1足さないとだめだし、曜日は漢字に当てはめないと。
こういうのを変数あらかじめ用意しておいてやるのってめんどくさいしね。
ちょっとした式を入れるだけなら@{[ ]}は便利ですね。
ちなみにqw(日 月 火 水 木 金 土)[ $clock[6] ]は、曜日の漢字を並べた配列の$clock[6]番目と。
実は月数が0から始まるのは、qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)[ $clock[4] ]とかするためです。
まぁ1から始まるにしても、この場合は1引いておけばいいだけですけどね。
ちなみにPHPにはヒアドキュメント内に式を埋め込める仕組みはないらしい。
だけど、短縮表記を許可してればの短縮形としてというのが使える。
をと書けるおまけですよ。
なので、HTML部分に円などと埋め込めますよ。
ちなみにPHPのroundは不思議な動作をするとか。だから意図した結果と違う結果が出るかも。
このネタを発見した人はPerlでCGI作るときにHTMLをヒアドキュメントで用意してたと。
この中で使いたかったという話ですから、これと同様のことをPHPでやるなら上のことかなと思ってね。

ゆうちょ銀行の口座に振り込みできそう?

今日からゆうちょ銀行の全国銀行データ通信システムへの接続が始まりました。
ゆうちょ銀行の通帳から他の銀行の口座への振込、
他の銀行からゆうちょ銀行の口座への振込ができるようになります。
他の銀行のユーザーからすれば便利になったのは確かですね。
イーバンクから電信振替相当のことができますからね。
まぁゆうちょの口座にあらかじめ入金しておけば、ゆうちょダイレクト使って家から電信振替できるけどね。
ただし、ゆうちょ側からは他行あては現金での振込ができない。
なので、実は郵便局に行けば手数料は高くてもどこへでも振り込めるというものではないんですね。
すでに通帳を持っている人が振り込むときだけ使える仕組みだということです。


郵便局に行く用事もないので、そっちがどうなってるかは知らない。
多分電信振替請求書風の紙を用意して待ってるんだとは思うけど。
ATMから3万円未満が210円、3万円以上が420円、
窓口から3万円未満は630円、3万円以上が840円となってます。
高いか高いかは一概には言えませんよね。
イーバンク銀行から他行は3万円未満が160円、3万円以上が250円だからね。
まぁここはインターネット専業だから特に安いわけですからね。
一方、僕がひいきにしてる某地方銀行の手数料だが、
ATMから3万円未満は315円、3万円以上が525円、
窓口から3万円未満は630円、3万円以上が840円、
ATMの手数料はゆうちょの方が安いといえる。イーバンクからやるから使わんけどね。
実はゆうちょの通帳を持ってれば、ATMでそんなに高くない手数料でどこへでも振り込めると。
そういうことですね。


さて、他行から振り込めるのは便利かも知れないね。
よく総合口座通帳の記号・番号で振り込んでくれと書いてあることあるけど、
ああいうのを支払うのにわざわざ郵便局行って、払うのめんどくさいからね。
多少手数料は高いけど、イーバンクからやれば家からでも払える。
というわけでできるかイーバンクにログインして確かめてみよう。
といっても手数料が惜しいので、暗証番号を入れる直前までしかやりませんが。
銀行名にゆうちょと入れれば検索にひっかってくれる、
支店は二二八店だからって ににはち と打つのはめんどくさいので、
店番号に228と打った方が速いですね。それで口座番号とかを入れると。
ここで受取人名を聞いてこないのだが、どうも時間内は照会できるみたいね。
次に進めば、受取人名が照会されて表示されるので、正しいか確認するだけでOK。
多くの銀行ではあまりに当然の仕組みだから、何も気にしてなかったかも知れないけど、
イーバンクでは最近になって対応するようになったんですね。(参考 : 口座情報自動入力サービスについて (イーバンク銀行))
逆にイーバンクの口座について他の銀行からも照会できるようになりました。
もちろん今までもイーバンクの口座については自動で受取人名が表示されました。
しかも漢字で。まぁえらいもんです。普通はカナですからね。
この仕組みを使うことで振込ミスを減らせるわけですね。
まぁ対応していることはわかりましたね。素晴らしいですね。


ゆうちょ銀行ってそんなにお金を貸すわけでもない変な銀行です。
そういう変な銀行というと、セブン銀行、イーバンク銀行とかかな。
ただしイーバンクは今年中にローンを始めるらしいですけど。
セブン銀行はATMネットワークを売りに、イーバンク銀行はインターネットでの決済を売りにしてた銀行ですね。
どちらもお金を貸して儲ける気はあまりないということです。
じゃあゆうちょ銀行って何なの?って多分決済銀行なんだろうねぇ。
だって、ゆうちょの窓口に行く用事って多くは振込ですしね。
青か赤の紙を持って払いに行くことはあるでしょう。
口座のない人に送金する方法というと、多分ゆうちょ銀行の為替になるんだろうなぁ。
手数料は3万円未満が420円、3万円以上は630円ですね。
手数料はこれだけなので、意外とお得かも知れない。
何よりも受け取れるところが多いですからね。ゆうちょ銀行の窓口とほぼ全ての郵便局だからね。
50円、100円、200円、300円、400円、500円、1000円に限れば定額小為替が手数料100円か。
これを普通郵便で送るだけ。
まぁ口座を知ってるなら使う価値はないぐらい手数料高いけど、知らなければこれが一番いいのかな。
ただし、あんまり儲かってないみたいですけどね。

置換かマッチか、対決してみようか

Perlでマッチした数を数えるにはどうすればいいかという話がある。
“123 51 5 65 25 14 25 12 54 65″の中にどれだけ\d+という正規表現にマッチするのがあるかということ。
今までどうやって調べればいいか知らんかったのよね。
で、どうも複数置換したときの返り値が置換した個数だというから、こうすればいいかなと。

print $s=~s/\d+/$&/g,"\n";

さっきのを$sに入れておくと、10と表示されるから、10個マッチすると言うことだな。
gを付けなければ1つずつしか置換してくれないのよね。
それで\d+にマッチしたものを$&に置換すると書いてあるが、
$&は特殊変数で、マッチした部分全部という意味。
$1,$2…は()でグループ化されたものの1番目、2番目…の意味だったけど、
他にもマッチ関係の特殊変数があるけど、まぁ$&はそれなりに使うのかな。
けどこれって、123にマッチしたら、これを123に置換するという意味だからね。
結局置換してないのよね。なんという効率の悪いプログラム。と思うわな。


それでいろいろ試してたのだが、どうも複数マッチというやつは2つ使い方があるらしい。

my @a=( $s=~m/\d+/g );
print "$_\n" for(@a);
print "$&\n" while( $s=~m/\d+/g );

1つは僕が何度もつかってるマッチした結果を配列にしてくれるやつ。
()でグループ化されてれば、その分だけいれてくれる。
結果をスカラーで受ければ、1つずつマッチして進むことができる。
それが3行目のwhileを使ったやつ。今まで知らんかったのよね。
これは、まず123にマッチして、次に51にマッチして…最後にマッチしなくなれば偽を返すと。
まぁPerlというやつはスカラーで受けるか配列で受けるかで動作が変わってしまうことが多いからね。
@aをスカラーとして取り扱えば@aの要素数だし、<>をスカラーとして取り扱えば一行読みこみだし…
まぁそういうことが複数マッチにもあったということです。
しかしこれを使えば個数を数えることをこうかける。

my $n=0;
$n++ while( $s=~m/\d+/g );
print "$n\n";

こっちの方が性能がいいに違いない。
なら確かめてみよう。


というわけでBenchmarkモジュールで試してみました。

use strict;
use warnings;
use Benchmark;
my $s='123 51 5 65 25 14 25 12 54 65 'x1000;
timethese(500,{
'replace'=>sub{ $s=~s/\d+/$&/g; },
'match' =>sub{ my $n=0; $n++ while( $s=~m/\d+/g ); }
} );

こんな便利なものがあるんですね。
timethese関数に試験する回数と試験名とサブルーチンリファレンスのハッシュリファレンスを渡すと。
今回ターゲットとした文字列は’123 51 5 65 25 14 25 12 54 65 ‘を1000回繰り返したもの。
この試験を500回やってもらったと。
本当は1000回ぐらいやればよかったんだが、実は結構時間がかかる。
徐々に増やしながらやったのだが、まぁ500回ぐらいやればいいかって。
結果ですが…

Benchmark: timing 500 iterations of match, replace...
match: 35 wallclock secs (33.88 usr + 0.00 sys = 33.88 CPU) @ 14.76/s (n=500)
replace: 6 wallclock secs ( 6.11 usr + 0.00 sys = 6.11 CPU) @ 81.85/s (n=500)

実はreplaceの方が圧倒的に速いんですね。
何でなんだろうね。けど不思議な話ですよね。
置換の方は繰り返しに特化されてるからかな。


それならばとこの2つのコードを比較してみることにした。

my @a1=();
while($s =~ m/^(.+?)\s+(.+)$/mg){
push @a1,[$1,$2];
}
my @a2=();
$s =~ s/^(.+?)\s+(.+)$/
push @a2,[$1,$2]; $&;
/emg;

mを付けると複数行の文字列の改行にも^と$が使えるようになりますからね。
行ごとに、test 100という行なら[‘test’,’100′]という配列リファレンスを作って配列に投げ込むと。
1つ目は複数マッチの方法。まぁそのままですね。
2つ目は置換にeオプションをつけたもの。
eオプションというのは、置換先をPerlのプログラムとして評価するもの。

$s =~ s/0x([0-9a-fA-F]+)/hex($1)/eg;

これは0x5Aとかにマッチして、これをhex(‘5A’)の結果でもって、90に置換すると。
それでこれはマッチしたものをpush @a2,[$1,$2]; $&;の結果に置換するというものだが、
結局これの結果って$&なんだよね。だから何も置換しない置換ということです。
さて、比較してみようか。

my $s="test 100\n"x10000;
timethese(100,{
'match' =>sub{ my @a1=(); while($s =~ m/^(.+?)\s+(.+)$/mg){ push @a1,[$1,$2]; } @a1; },
'replace'=>sub{ my @a2=(); $s =~ s/^(.+?)\s+(.+)$/ push @a2,[$1,$2]; $&; /emg; @a2; }
} );

test 100と10000行繰り返したものに処理することを100回するベンチマークね。
結果だが、こんな風になった。

Benchmark: timing 100 iterations of match, replace...
match: 39 wallclock secs (37.77 usr + 0.03 sys = 37.80 CPU) @ 2.65/s (n=100)
replace: 9 wallclock secs ( 8.19 usr + 0.11 sys = 8.30 CPU) @ 12.05/s (n=100)

と、eオプション付きの置換の方が高速でした。
しかし1000行なら少し速いかなという程度、100行だとマッチの方が速いぐらい。
普段1000行も処理しないだろうし、好きな方で書けばよさそうですね。
そしてとんでもない回数の繰り返しには複数置換が向いていることがよくわかりましたね。


まぁPerlというのはやり方はいろいろあるわけで、好きな方法で書けばいいのは確かですね。
けど性能がいいとか欠きやすいとかあるから、これがいいですねというのもあると。
僕の感想では個数数えるのは置換の方がいいですね、
けど別にそれ以外はわかりにくい書き方してやる必要もないだろうと。
明らかに見にくいしねぇ。何してるんだ?と思われること間違えなし。
ただ知っておくと面白いとは思うけどね。

忘れ去られた電信のさす電報

ふと思ったのだが、なんかイベントあると、お祝いとか言って電報とか届きますよね。
けど電報って高いのよね。
そもそも電報というのは物事を遠くに高速に伝えるために使われた仕組みですよね。
今は無理ですけど、昔なら電報取扱所に言って申し込んだら、
電信でもって、宛先の近所で印刷されて、これを配達すると。そういう仕組みです。
西日本電信電話株式会社の電信は電報のことですね。
だから申し込んでから日本国内ならどこでも3時間ぐらいで届くらしいです。
まぁ確かに速いですよね。ただ今は多くの家に電話がありますから、そんなに使う必要はないのですが…


で、電報の値段なのですが、一般的に使われる115から申し込む方法では、
基本料金が税込504円で、25文字を超えた分からは5文字あたり63円となってます。
ただし、これは一般扱いの漢字電報で、慶弔扱いだと大幅に高くなります。
あとかな電報だと、基本料金が357円、25文字以上5文字あたり42円です。
だけどかな電報だと文字数がかさむからどっちが安いかはよくわからない。
漢字電報は濁点・半濁点も課金されないし、案外安いかも。
あと台紙料金もかかるけど、どんな扱いでも0円の台紙があるので。
それとD-MAILから漢字電報は申し込めるけど、これだと42円引かれる。
さて、25文字というとどれぐらいかけるのだろうか?ちょっと試してみよう。

明日八時から会議、七時半に集合せよ
                      ジェンカイ錬金術

ちなみに空白改行は課金されません。これで25文字ぴったりです。
まぁ意外にたくさん書けるんじゃないかと思いますけどね。
これをD-MAILから出せば462円で、19時までに申し込めば当日中に配達だから、
急ぎの知らせで、電話がないとなれば結構使えるんじゃないかなと。
ただ電話がない人はかなり少ないと思いますが。
電話があるなら電話かけた方がずっと速くてずっと安いですね。


ところでレタックスというやつがあるのですが、
これは受け取った郵便局と宛先の支店の間をファクシミリを使って送る、すごく速い速達ですね。
まぁ仕組みは電報に似ているかなと思うけど。
これはA4の用紙に書いて送る仕組みになってます。まぁ用紙の一部は宛名なんですけどね。
お値段ですが580円です。一般的な台紙か封筒に入れて送る場合ですが。
電報と比べると安めですね。漢字電報でD-MAILからだと35文字で586円だから、
35文字以上送るよりかはレタックスの方が安いと。
しかもFAXで送るから、なんでも書ける。
ただし都合が悪いのは、郵便局に行って出す以外は非常に具合が悪い。
だから実質的には郵便局の窓口から出すしかない。
ただ逆に言えば窓口に行けば出せると言うことですけどね。
電報は現在では電話かインターネットから出す以外はほぼ不可能なんですね。
公衆電話から出そうにも料金はクレジットカード払い。だから使えない人もいるかも。
けどレタックスなら窓口に行って、専用用紙もらって伝えたいことを書いて、料金を払えばOK。
ただ、15時までに出さないと当日配達してもらえませんからね。
普通の速達よりかはかなり有利だけど、電報には劣る。


なんやら書いてきましたが、そんなに急ぎで送る用事もなかろうと。
というのも現在の郵便事情は非常によいので、広い範囲が翌日配達なんですよね。
翌日配達の地域は速達を付ければ午前中には届きます。
翌々日の地域でも速達を付ければ翌日中には届きます。
まぁ地域によるんだろうけど、速達の意味はそれなりにあるみたいです。
だから前日中に速達で出しておけば結構使えるんじゃないかということ。
当然値段も安いよ。郵便料金は25g以下の定形郵便物なら速達付きで350円。あと紙代。
まぁあまりに遠いとなればそりゃレタックスとかの方がいいですけどね。
しかし、結局電報ってなんなんだというのはすごく疑問ですよね。
けど電報が残ってるってことは、それなりには使われていると言うことだよな。
レタックスは郵便局と支店にファックスを置くだけだし、
配送部門は郵便と一緒だからまぁ儲からないにせよやめるまではいかないだろうなとは思うけど。
何でなんだろうね。

不思議な年賀状の消印の話

送れて出したであろう年賀状が届いた。
1月1日は特別だから配達するのは当然かも知れないけど、
2日も配達してくれるとはね。
しかも期限を越えて出したであろう郵便を。
まぁたった1日遅れで届くとはがんばってるなぁと思いますけどね。
しかし、実際期限を越えてるかはわからないんですけどね。


なんでわからないのかという話ですが、
年賀はがきには消印を押さないからですね。
なんでなんだろうね?手間になるからかな。
料金の刷り込まれた年賀と書かれた郵便はがきは消印を省略するということ。
だから年賀と書かれていても切手で料金を払うときは消印が押されますよ。
けどこれって結構紛らわしいんですよね。
存在しない住所を書いて送ると、郵便は戻ってきます。
ところが消印が押されてないので、一体これはどうなのかわかりにくい。
というか相手に届かないにしても郵便料金はかかってるはずなのよね。
普段なら発送された郵便支店で消印を押してからいろいろするから、
こうやって返ってきた郵便は消印が押されているので再利用できないことは自明。
実際そんなことがあったのね。けど消印が押されてないから、うーん…となるわけ。
ちなみに特に依頼すれば消印は押してくれます。
年賀はがきを切手を貼った郵便のところに投げ込むだけでしょうし。
ただし、実際の所消印が押されてても期間内に出されたかはわかりませんけどね。
というのも、年賀の取り扱いをする郵便は前年に出しても元日の消印が押されるから。
まぁなんでって、新年のご挨拶なんだから、新年になってから出した方が形式的にはいいでしょ。
配達の手間を考えて前年中に出してもらってるけど、
本当は新年になってから出すものだからこういう消印になると。
単に新年まで配達しない郵便ではないということです。


まぁしかし消印押されてる郵便はほとんどないですよね。
届いた年賀状をパラパラ見てましたが、我が家全体で1通だけ。
まして料金別納・料金後納の取り扱いをする郵便はなかった。
ついでにいうとその1通以外全部お年玉のくじ付きの年賀はがき。
まぁそりゃそうですよね。
あとほとんどが普通紙か普通のインクジェット用でしたね。
写真用というのもあるんですけど、気付いた分では1通だけだったかな。
まぁあんまり変なことをする人はいないということですね。