PythonでBoyer-Moore法

ProductName Mastering Algorithms With Perl
Jon Orwant
Oreilly & Associates Inc / 2553円 ( 1999-07 )


perlは写経でいまいち理解度があやしいため、pythonでBoyer-Moore法を。パターンとの不一致の場合には何文字スキップできるか、一致した場合に何文字スキップできるかのテーブルを最初に作っておいて、スキップ幅の大きいほうでスキップしながらパターンマッチを進めていく。

def boyer_moore_bad_character (P):
   m = len(P)
   bc = [m] * 256
   j = m
   for char in list(P):
       bc[ord(char)] = j - 1
       j -= 1

   return m, bc

def boyer_moore_good_suffix (m,P):
   j = m + 1
   gs = [0] * j
   k = [0] * j
   k[m] = j
   for i in reversed(range(1,j)):
       while j <= m and P[i-1] != P[j-1]:
           if gs[j] == 0:
               gs[j] = j - i
           j = k[j]
       j -= 1
       k[i-1] = j

   kn = k[0]
   for j in range(m+1):
       if gs[j] == 0: gs[j] = kn
       if j == kn: kn = k[kn]

   gs.pop(0)
   return gs

def boyer_moore (T,P):
    (m,bc) = boyer_moore_bad_character(P)
    gs    = boyer_moore_good_suffix(m,P)

    (i, last_i, first_j) = (0, len(T)-m, m-1)

    for i in range(last_i+1):
        j = first_j
        while j >= 0 and T[i+j] == P[j]:
            j -= 1
        if j < 0:
            return i
        else:
            bcn = bc[ord(T[i+j])] - m + j + 1
            gsn = gs[j]
            i += bcn if bcn > gsn else gsn
    return -1

if __name__ == '__main__':
    print boyer_moore("perlpypythonruby","python")
  • pythonはコードの見通しがよいですな
  • perlと違ってsubstrとかやらなくてもいいので見通しがよい
  • perlのshiftがpop(0)なのがあれ。先頭をpopするってのが。
  • perlだと$a[5]=5とやれるけど、pythonはそれ以前の要素が自動的ににundefで埋まらない

for文でカウンタ変数使いたかったのでrangeをつかったけどPython流はどうやるのがよろしいんだろうか、、、カウンタ変数減算するのにfor i in reversed(range(1,j))だしな。

pythonで単語の頻度をカウントするには

perlだと

for my $word (@word_list) {
  $count{$word}++;
}

とかできるのだけど、pythonだとループの内部で

if count.has_key(word):
    count[word] = count[word] + 1
else:
    count[word] = 1

とかやって、キーがあるのかないのか調べないといけないようだ。

もっとスマートなやり方あるような気もするんだが。

optparseでコマンドラインオプション解析

perlでいうGetopt::Long のようなものはgetoptでおこなえる。が、pythonにはさらにoptparseなるものがあるらしいので、今回そっちを使ってコマンドをつくってみた。

6.21 optparse -- より強力なコマンドラインオプション解析器

optparse モジュールは、getopt よりも簡便で、柔軟性に富み、 かつ強力なコマンドライン解析ライブラリです。 optparse では、より明快なスタイルのコマンドライン解析手法、 すなわちOptionParser のインスタンスを作成してオプションを 追加してゆき、そのインスタンスでコマンドラインを解析するという手法を とっています。optparse を使うと、GNU/POSIX 構文でオプションを 指定できるだけでなく、使用法やヘルプメッセージの生成も行えます。

オプションとヘルプ用の情報を一緒にaddする。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#!/usr/bin/python

import sys, re
from optparse import OptionParser

parser = OptionParser()
parser.add_option("-i", "--input", dest="input",
                 help="read from MOL2 FILE", metavar="FILE")
parser.add_option("-o", "--output", dest="output",
                 help="write to GAMESS INPUT", metavar="FILE")
parser.add_option("-t", "--type", dest="type",
                 help="select calcuiation type", metavar="TYPE")

if __name__ == "__main__":

   (options, args) = parser.parse_args()

-hでヘルプが出力される。

$ ./test.py -h
Usage: test.py [options]

Options:
  -h, --help            show this help message and exit
  -i FILE, --input=FILE
                        read from MOL2 FILE
  -o FILE, --output=FILE
                        write to GAMESS INPUT
  -t TYPE, --type=TYPE  select calcuiation type

pythonで改行コードを取り除く場合

perlだとchopとかchompとかしますが、pythonだとどうするんだろうか?

最近はこんな感じ

for line in open(filename,"r").readlines():
    choped_line = line[:-1]

こういうやり方もあるらしい。

for line in open(filename,"r").readlines():
    choped_line = line.rstrip('\n')

今のところは改行コードをstripするというメソッドよりは, 文字列の0-最後から-1番目っていう前者のほうがなんとなくわかりやすいかなと思う。

PythonでOracleにアクセスしてみる

pythonでOracleにアクセスするにはcx_Oracleを使うと良いらしい。

Cafe de Paison: cx_Oracle

cx_Oracle はOracleデータベースを操作する機能を提供するPythonの拡張モジュールです。 www.python.orgが提唱する Python DATABASE API 2.0 にも準拠しており、 幾つかあるPythonのOracleモジュールの中でも特に完成度が高いソフトウェアです。

FC2に10gのクライアントをインストールしたマシンがあったので、FC5用のRPMをインストールしてみたらさくっと入った。なんかあっけないほど簡単だった。

これで、9iのインスタンスに接続してみる。

import sys, string, cx_Oracle

filename = "test.csv"

con = cx_Oracle.connect("user/pass@orc")
ora = con.cursor()

s = "select max(id) from sample_table"
ora.execute(s)
max_id = ora.fetchone()[0]

print max_id

ora.close()
con.close()

なんかDBIみたいだ。

パイソニスタになるんや、とふと思った

最近、仕事がつまらんなぁと。つまらない理由はいろいろあるのだけれど、なんか自分のやりたいことと今の仕事にずれがあってそれが徐々に大きくなってるような気がするとかしないとか。

で、つまらんつまらんと言ってても時間の無駄なので、なにか達成感の得られるものでもということで、職場ではPythonオンリーで行くことにしてみた。

slurp mode

pythonでファイルの一気読みってどうやんのかなと思ったが

all_data = open('some.txt', 'r').read()

でいいのね。perlだと

$fh->open("some.txt", '<') or die;
my $file;
{
   local $/;
   $file = <$fh>;
}
$fh->close;

初めてのmoinmoinマクロ

moinmoinにamazonのアソシエイトを貼り付けたくてマクロを作ってみた。といってもISBN.pyをいじっただけだけど。

html_code = """
<iframe src="http://rcm-jp.amazon.co.jp/e/cm?t=kaerutyuuihou-22
&o=9&p=48&l=st1&mode=%s&search=%s&fc1=000000<1=&
lc1=3366FF&bg1=FFFFFF&f=ifr" marginwidth="0"
marginheight="0" width="728" height="90" border="0"
frameborder="0" style="border:none;" scrolling="no"></iframe>
"""

def execute(macro, args):
    f = macro.formatter
    result = ''
    if args:
        args = [arg.strip() for arg in args.split(',')]
    else:
        args = []
    if 1 > len(args):
        result += f.strong(1) + \
                  f.text('Example: [[AMAZON("books-jp","perl")]]') + \
                  f.strong(0) + \
                  f.text(' - links to Amazon')
    else:
                result += html_code % tuple(args)
    return result

で、

result += html_code % tuple(args)

の部分で最初リストを突っ込んでたせいでエラーが出てたのだけど理由がわからなかった。

っていうか差し込む場合に何でタプルでないといけないのかわからん。リストだ問題あんのかな?

Python Cookbook

アマゾンのusedで3000円で出てたので即買い。

ProductName Python Cookbook

Oreilly & Associates Inc / 3649円 ( 2005-05-05 )


オライリーの本は結構買ってるけど、クックブック買うのは実は初めてだったりする。(Perlのクックブックも買ったことない) クックブックなので、引きながら使うのがいいんだろうけど、とりあえず一通り流して読んだ。

クイックソートはhaskellみたいにかける。

def qsort(L):
    if len(L) <= 1: return L
    return qsort([lt for lt in L[1:] if lt < L[0]]) + \
    L[0:1] + qsort([ge for ge in L[1:] if ge >= L[0]])

リスト内包表記ができるから?

チャプターごとにまとまっていて、特に気になる章は、GUIプログラミングの章と、デバッグ、テスト、スレッドプログラミングの章。

WindowsでGUIプログラミングするならIronPythonなどいいのかなとか思ってる。いまのとこWindowsのGUIにはあまりタッチしなさそうだけど、知っとくと便利かな。

あとは、jythonなんかにも少し触れられてる。

catwalkの使い方がメインのスクリーンキャスト

TurboGearsのTrac にスクリーンキャストが幾つかあったので英語の勉強も兼ねて見てた。

TurboTunesTutorial.movでCatwalkの使い方が解説されてた。

Turbogears(SQLObject)でSQLのトレース

DBICの場合はexport DBIC_TRACE=1でOKなんだけど、SQLObjectだと_connection.debugアトリビュートにTrueを突っ込むらしい。

Personってクラスがある場合

Person._connection.debug = True

これで実際に発行されるSQL文がトレースできる。

が、個々のクラスでこんなことするのは結構めんどくさいので、DBICみたいに環境変数で設定できないかと調べた。

seraphyの日記 - Pyhon2.5でSQLObjectを使ってみる

コネクションのURIにパラメータとして「Debug=True」と指定しているため、実行時にSQLObjectのトレース情報がコンソール画面に表示される。

URIにパラメータ渡すようにすればいいらしいので、環境変数がセットされているかどうかでURIにパラメータ渡すかどうか決めるように設定ファイルをいじればよいみたいだ。