83's

Top > Archives > 2006 > April

April 06, 2006

JumanのRubyバインディング 19:36

Jumanの RubyバインディングRuby-Jumanを作ってみたよ。

(; ・∀・)つ[rubyjuman_wrap.c] サッ

SWIGでやったので、そのファイルもうpしときますね。これ使えばPerlとかもいけるんではないかと。

ホントカヨ…(; ・∀・)つ[rubyjuman.i] コソーリ

$ tar zxvf juman-5.1.tar.gz
$ cp rubyjuman_wrap.c juman-5.1/lib
$ cd juman-5.1
$ ./configure
$ make
(# make install  ←Jumanがインストールされていない場合)
$ cd lib
$ gcc -c -fPIC -I/usr/lib/ruby/1.8/i386-linux rubyjuman_wrap.c
$ gcc -shared *.o -o Juman.so

-Iのところは人それぞれ。ruby.hのあるディレクトリを指定。

なんかmakeとか良くわかんない。こんなんでいいのかな。一応動いたけど。

できあがったJuman.soを一応確認。

$ ls
Juman.so*    getid.lo    japanese.c    katuyou.c  ……
$ irb -r Juman
irb(main):001:0> Juman.init
=> nil
irb(main):002:0> $KCODE = 'E'
=> "E"
irb(main):003:0> puts Juman.parse("徹夜でネットしてました。")
徹夜 てつや 徹夜 名詞 6 サ変名詞 2 * 0 * 0 "代表表記:徹夜"
で で で 助詞 9 格助詞 1 * 0 * 0 NIL
ネット ねっと ネット 名詞 6 普通名詞 1 * 0 * 0 "代表表記:ネット"
して して する 動詞 2 * 0 サ変動詞 16 タ系連用テ形 11 "付属動詞候補(基本) 代表表記:する"
ました ました ます 接尾辞 14 動詞性接尾辞 7 動詞性接尾辞ます型 31 タ形 5 NIL
。 。 。 特殊 1 句点 1 * 0 * 0 NIL
=> nil

うまくいったら、Juman.soを/usr/local/lib/site_ruby/1.8とかそういうところにコピー。

使い方。

require 'Juman'

#初期化
Juman.init

#1文を形態素解析
Juman.parse(sentence)

出力形式は、jumanのデフォルトです。つまりjumanってやっただけ(またはjuman -B -e2)と同じ。

オプション渡せるといいんだけど、どうも-eと-e2のコードしか書かれてないように見えたので、 めんどくさいから-Bも固定。

以前同じように作ろうとして失敗してたのは、 オプションを格納する変数を初期化してなくて(当然-eでも-e2でもなくて)、 パースしても出力がmallocされなかったためにこけたのではないかと推測。

とりあえずソースほっとんど読んでないうえにヘタレなので、はっきり言って自信ないです。 しかも多分自分使わないので、これ以上良くなるわけもなく。 できればエロい人にもっといいものを……。

そういえばreturn書き忘れたり、ifの前に(を書いてしまったり(←これ5回はやった)した。 そろそろC書けなくなるかも……。

April 12, 2006

ゼミで使う本 02:52

Speech and Language Processingを Amazonで注文。値段…orz

Red Hat Enterprise Linuxのpostfixの罠にはまる 13:53

研究室のメーリングリストを作るために(去年のメーリングリストサーバは学校に返却してしまった) postfixとfmlを設定。

去年やったときはpostfixの設定なんてろくにせずにうまくいってたんで そこでつまづくことはないだろうとなめてたんだけど、今回はそうではなかった。

メールサーバはなんもわかってないので、どこに問題があるのかを突き止めるのが大変だった。 でもその過程で少しメールサーバの勉強になるところがLinuxメソッド。疲れたけど。

結局Red Hatのpostfixのデフォルトの設定が(俺に)悪さをしてた。

初めに見つけたのはmain.cfのこれ。

inet_interfaces = localhost

localhostだと、localhostからのメールしか送れないらしい。 もともとは制限なしのallがデフォルトらしいけど、セキュリティ上の理由でRed Hat版はこうなってるのかな。 てことで、

inet_interfaces = all

それでも送れない。最終的にaliasがうまくいってないみたいってことがわかり、 main.cfを眺めていると……

alias_maps = hash:/etc/postfix/aliases

ちょwwww そんなファイルは知らねーよw

alias_maps = hash:/etc/aliases

に変更。あー、/etc/aliasesをいくらいじってもうまくいかないわけだわ。

ちなみにこれももともとのデフォルトは/etc/aliasesのほうなので、 Red Hatのpostfixが意図的にこうなってるみたいヽ(`Д´)ノウワァァン!!

April 13, 2006

1コマ目寝坊 18:38

授業開始4日目にしてこれか……。

とりあえず今日は3時に来て、研究室のネットワークを整備。 これで全部屋つながった。 そして去年使わずに放置していたUPS2つをやっと使う。

このあとのTodo。

  • 4年生にプログラミング環境構築指示
  • 4年生のプログラミング課題の作成
  • CMSのセットアップ
  • 内部DNSを設定
  • 超ハイスペックなWindowsサーバの利用方法を考える(WindowsワカンネからLinux入れたい……)

まだある気がする。

てか、ここ1カ月研究が進んでないような。ブログ作る暇ねーー。 1年半以上前に作ったこのブログにもうちょっとがんばってもらうか……。

April 14, 2006

3つの○ 13:23

この微妙な違いを使い分けることができる人いるの?

irb(main):001:0> "〇"
=> "\241\273"
irb(main):002:0> "○"
=> "\241\373"
irb(main):003:0> "◯"
=> "\242\376"

ちなみにEUC↑

April 16, 2006

awkに遭遇 01:44

反応するところが違うんだけれども。

起動時間だけを表示するには、

$ uptime | awk '{ print $1 }' します。

ほうほう。awkって見ないんでどんなのか知らなかったけど、意外とナイス。

uptimeは

yz@ubuntu:~$ uptime
 01:03:24 up  2:52,  2 users,  load average: 0.21, 0.33, 0.32

という出力だけど、上のは

yz@ubuntu:~$ uptime | awk '{print $1}'
01:25:20

となる。スペースを区切り文字として、それぞれを$1, $2…と順に参照できるみたい。

Rubyのワンライナーだと

yz@ubuntu:~$ uptime | ruby -F -nae  'puts $F[0]'
01:26:01

eのあとにオプション置いちゃって動かなくてはまった。萎え。

簡易CSVカラム抽出。

yz@ubuntu:~$ cat a.csv
1,b,3
2,3,4
c,3,4
yz@ubuntu:~$ awk -F, '{print $2}' a.csv
b
3
3
yz@ubuntu:~$ ruby -F, -nae 'puts $F[1]' a.csv
b
3
3

Rubyで十分な気がしてきた……。 Rubyは区切り文字のデフォがnilなのでそこがうざいかも。

こんなのもあった。

yz@ubuntu ~% uptime | cut -d\  -f 2
22:02:19
yz@ubuntu ~% cut -d, -f 2 a.csv
b
3
3

April 17, 2006

alt押しながらドラッグ 00:35

とりあえずGnomeで確認しただけだけど、 alt押しながらウィンドウのどこかをクリックしてドラッグするとウィンドウを移動できるんだね。 知らなかった。

何様だよw みたいな 18:19

ほんとバカバカしいんですが、去年の卒論生のプログラミングのデキが やばかったんで、今年は4年生に週1のペースで簡単なプログラミングの課題をやってもらうことに。 それを提案したのも進めていくのもオレなんですが、 学生が学生に課題を出すってなんかアホくさい。

オレは偉くもすごくもないし、成績は下から数えると計算量が格段に小さくなる感じだし。 ただ、来年の4年生にいい人材を期待するなら今年おもしろい卒研をやってもらわないと困るんですよ。

でも確実にオレは研究室で浮いてきそうですね、こんなことしてると。 プログラミングとかLinuxとか興味持ってくれるやつがいれば話は別だけど。 まー実際この学部の一般的な人とはやってることが違うから仕方ないか……。 ネットワーク管理担当になった4年生に期待……。

第1回はPerlやRubyに慣れようということで、SICPから問題を拝借w  自然言語処理と直接関係はないけど。 オレはこれから自分で出した課題をSchemeでやっていこうと思いますw

(define (average x y)
  (/ (+ x y) 2.0))

(define (search f nega posi)
  (let ((mid (average nega posi)))
    (cond
      ((close-enough? nega posi) mid)
      ((negative? (f mid)) (search f mid posi))
      ((positive? (f mid)) (search f nega mid))
      (else mid))))

(define (close-enough? x y)
  (< (abs (- x y)) 0.001))

(define (half-interval-method f x y)
  (let ((fx (f x))
        (fy (f y)))
    (cond
      ((and (positive? fy) (negative? fx)) (search f x y))
      ((and (positive? fx) (negative? fy)) (search f y x))
      (else (display "error")))))

;πを求める
(display (half-interval-method sin 2.0 4.0))
(newline)
;eを求める
(display (half-interval-method (lambda (x) (- (log x) 1)) 2.0 3.0))
(newline)
3.14111328125
2.71826171875

April 20, 2006

vimで段落の整形 03:36

vim6.3でのびぼーろく。

日本語の整形に対応していないらしいので、香り屋から gvimを落としてきて、中にあるruntime/plugin/format.vimを~/.vim/pluginにコピー。

ヘルプ(:h formatting)によると、段落の整形にはgq{motion}とgw{motion}がある。 でもコピーしたformat.vimはgqのほうしかサポートしていないみたい(gw{motion}が使えないぽい)。

ここで、{motion}てのは移動系コマンド。例えばgq}とやれば、現在の位置から 段落の最後までが整形対象になる。また、現在の行だけ整形するにはgqqとする。

多分ここで使える特殊なコマンドなんだろうけどapってのがあって、 gqapで現在の段落が整形対象になる。これが欲しかったやつ。 前にビジュアルモードでgqしてたけど、gqapのほうがいいですね。

で、これ、formatoptionsにaが指定されてるとなんかおかしくなるような。 このオプションは(英語のときは)テキスト入力中に自動で整形してくれるんだけど、 format.vimを使っても日本語には結局効かなかったので指定しなくていいや。

あとはgqapって長いからなんとかしたいわけだけど、

nmap gq gqap

ってやってみたらおかしいし遅いし。ああああああああ、vimのカスタマイズって 全然わかってないオレ。どうしたらいいんだーーーーーヽ(`Д´)ノ ウワァァァン

てことで気になって眠れないので今日の1コマ目の履修はやめます。

Feedのrate 04:33

LivedoorのRSSリーダにはレートを使ったフィードの評価の 機能がついてる。

ちょwwwwwwww 3月の終わりにこんなの作ってたんですがwwやられたなぁwww
Bloglinesにmy rate

簡単に燃えつきるんじゃなかったorz あんなすごいの出ちゃうと、もうやる気ナッシング。 むしろLivedoor Readerを使いたくなった。

この前もtakkan_mと アイデアを練って、さあ卒論終わったら実装だって言ってたら、同じコンセプトのやつ出てがっくりしたなぁ。 coCommentってやつ。 まー俺らの実装より高機能なんだろうけど、そう思うと作る気なくなる……。

なんか「そのうち作ろう」って思ってるとオレよりすごい人が オレのより良いもの作って萎えるので、 一つ集中してやりとげるべきかもしんない。

とりあえずこのrateと、あともう一つ前々から作りたかったアイデアがある。 これもこの前近いことをやり始めた人がいるから、早くしないと!  でも二兎を追うといいことないしなぁ。rateはやめるか……。

にしても、最近リニューアルしたAmazonをしっかりインスパイアしてるのもLivedoorクオリティww  GJwwww

livedoor Reader + mozlessがいいかも 18:50

livedoor Readerなかなかナイス。

mozlessは今まで使ってなかったんだけど、 livedoor Readerのpとoのショートカットキー(まとめ読みのキー)が 最強過ぎるので、oで開いたページをlessのキーバインドで見て、閉じて、とやってけば快適な予感。

April 22, 2006

やじるし 15:01

livedoor Readerはβ版らしいですが、それでもこの快適さ。 Bloglinesに未練なし、です。やっぱ軽さは大事。

ただ、気になるのがこれ。

livedoor Readerの矢印ボタン

上の画像の矢印なんだけど、これ見ても正確に使い方が伝わってこないんですが。

で、実際に押してみると右の矢印は次のエントリや次のフィードに行くじゃないすか、下にスクロールして。 左の矢印を押すと上にスクロール。なんで左右の矢印なのかわからない。

上下矢印とか、「前」「次」とかのほうがいいと思うんだけど、 何かオレの気づいていない理由というか、 左右矢印が訴えているものをオレが鈍くて感知できてないとか、そういうのありますか?(><;)

少なくともブラウザの「前のページ」「次のページ」の矢印とは別の意味の矢印ですよね??

まとめ読みにつられた 15:41

ん、ついついlivedoor Readerの目玉機能?のまとめ読みに 引っ張られる形で新しいタブ開いて見たりしてたけど、 いつもは読みにくくなければリーダで読んでいたんだった。 いちいち開くの('A`)マンドクセ

まー例えまとめ読みが無かったとしても、サクサクいけるんでBloglinesよりは良いかな。

April 24, 2006

Vine SeedにRuby 1.8.4が! 00:56

きたきた。ruby 1.8.4

Vine SeedはGnomeとかちょっぱやで最新のがあがってくるけど、 Rubyはついこないだまで1.8.2のふりをした1.8.1でした。

個人的にはkconvがutfに対応してなかったのが嫌だった。 どんだけ優先度低いんだろう、VineにとってのRubyは。

やじるしかわってる! 20:12

livedoor Readerのやじるしが……って書いた最速の人に捕捉されてたんで「(;^ω^)おっおっ」と思ってたら、 今日やじるしかわりましたね。

ブログはすげーなぁ……。 こんな辺境のブログに書いたエントリも、 拾おうと思えば拾えるんだもんなぁ……。

April 26, 2006

wcコマンドもどき 01:18

さて、研究室の4年生向けのプログラミング課題2回目。 今回はGW挟むので、前回よりは多めに出してみました。

とりあえず今回も慣れないScheme(Gauche)でオレもやってみます。 時間が無いのでまず1つ目だけ。行数と単語数を表示するwcコマンドもどき。

(use srfi-13)

(define (print-result n-lines n-words)
  (format #t "~s lines\n" n-lines)
  (format #t "~s words\n" n-words))

(define (number-of-words line)
  (let ((str (string-trim-both line)))
    (if (string-null? str)
      0
      (length (string-split str #/\s+/)))))

(define (main args)
  (call-with-input-file
    (cadr args)
    (lambda (in)
      (let loop ((n-lines 0)
                 (n-words 0))
        (let ((line (read-line in)))
          (if (eof-object? line)
            (print-result n-lines n-words)
            (loop (+ n-lines 1)
                  (+ n-words (number-of-words line)))))))))

むう。

gosh> (string-split "" #/\s/)
("")

どうよそれ。()を返してくれればnumber-of-wordsのif文が消せるのに。

あ、でもsplitされずに入力文字列がそのまま返るっていうことで

gosh> (string-split "a" #/\s/)
("a")

と同じ意味でつか。じゃーさっきのも("")でいいんだ。

するとRubyのsplitはどうなんだろう。

>> "".split /\s/
=> []
>> "a".split /\s/
=> ["a"]

""と"a"で扱いが違う。どちらも文字列なのに。

どっちが自然なんだろう……。

英語しんどい 13:05

小学校のころ国語の教科書を読んでこいっていう宿題があって、 「うわー、こんなに読むのかよめんどくさい。読んだことにしちゃえ」っていうあの時の感情、 それが今、授業の教科書になってる洋書を前にして再来。

オレの英語の力が小学生レベルなのがよく分かって鬱。

sortコマンドもどき 15:46

課題の続き。Gaucheで。

行ごとの単純なソートプログラム。

(define (read-lines port)
  (let ((line (read-line port)))
    (if (eof-object? line)
      '()
      (cons line (read-lines port)))))

(define (main args)
  (for-each (lambda (line) (display line) (newline))
            (sort (read-lines (open-input-file (cadr args)))
                  string<?)))

ふむふむ。にしても、上のread-linesみたいに一気に読み込む関数はないのかな。 毎回コーディングするの?

あとfor-each proc listsort list procmap proc list。 引数の順番統一できなかったのかな。listを複数渡すことを考えると proc listと来るべきで、そうするとsortが乱してる? あ、 sortに渡す手続きは省略可能なのか。それでですか。 その点、オブジェクト指向言語は作用されるものが明快に書けていいですね。

次は2つ目のカラム以降でソート。sort -k2 fileと同じ感じに。

(define (main args)
  (for-each (lambda (line) (display line) (newline))
            (sort (read-lines (open-input-file (cadr args)))
                  (lambda (a b)
                    (let ((str1 (rxmatch-after (#/\s/ a)))
                          (str2 (rxmatch-after (#/\s/ b))))
                    (string<? str1 str2))))))

string-scanに 正規表現が渡せると便利でいいですよねぇ。 文字か文字列しか受け付けないんじゃ、そんなに使わない希ガス。

残り課題あと1つ。

単語の頻度カウント 18:43

課題の最後。ハッシュテーブルを使って単語の頻度を数え、 頻度の高い順にソートして表示してください、というもの。

Rubyなら詰めなくても10行いらないくらいだろうけど、さて……。

(use srfi-13)

(define (split-line line)
  (let ((str (string-trim-both line)))
    (if (string-null? str)
      '()
      (string-split str #/\s+/))))

(define (hash-table-inc ht key)
  (hash-table-put! ht key (+ 1 (hash-table-get ht key 0))))

(define (count-words ht word-list)
  (for-each (lambda (word) (hash-table-inc ht word))
            word-list))

(define (hash-table->list ht)
  (let iter ((result '())
             (keys (hash-table-keys ht)))
    (if (null? keys)
      result
      (iter (cons (list (car keys) (hash-table-get ht (car keys)))
                  result)
            (cdr keys)))))

(define (print-hash-list hl)
  (for-each (lambda (x) (format #t "~d\t~a\n" (cadr x) (car x)))
            (sort hl
                  (lambda (a b)
                    (> (cadr a) (cadr b))))))

(define (main args)
  (let ((word-count (make-hash-table 'equal?)))
    (call-with-input-file (cadr args)
                          (lambda (in-file)
                            (let loop ((line (read-line in-file)))
                              (if (eof-object? line)
                                (print-hash-list (hash-table->list word-count))
                                (begin
                                  (count-words word-count (split-line line))
                                  (loop (read-line in-file)))))))))

(´;ω;`)ブワッ まだまだダメだ……orz

RubyにおけるHash#to_aが見当たらなくてhash-table->listってのを作ってるけど、 それを差し引いても30行……。書式が違うとは言え……。グローバル変数使ってないからかな……。 なんとかなりませんかねこれ……。

あら、Hash#to_a見つけた。 hash-table->alistってのがあったんで、hash-table->listは削除。

(use util.list)
(use srfi-13)

(define (split-line line)
  (let ((str (string-trim-both line)))
    (if (string-null? str) '() (string-split str #/\s+/))))

(define (hash-table-inc ht key)
  (hash-table-put! ht key (+ 1 (hash-table-get ht key 0))))

(define (count-words ht word-list)
  (for-each (lambda (word) (hash-table-inc ht word))
            word-list))

(define (print-hash-table ht)
  (for-each (lambda (x) (format #t "~d\t~a\n" (cdr x) (car x)))
            (sort (hash-table->alist ht)
                  (lambda (a b)
                    (> (cdr a) (cdr b))))))

(define (main args)
  (let ((word-count (make-hash-table 'equal?)))
    (call-with-input-file (cadr args)
                          (lambda (in-file)
                            (let loop ((line (read-line in-file)))
                              (if (eof-object? line)
                                (print-hash-table word-count)
                                (begin
                                  (count-words word-count (split-line line))
                                  (loop (read-line in-file)))))))))

まだ気持ち長い。 なんとなくmainの中が汚い気がする。 もちっとうまくいかないかな。

April 29, 2006

単語の頻度 その2 16:56

課題も後半は重くなってくるので、今のうちに次の課題を考えておく。

次回は標準入出力をテーマにしたいんですよね。

まずuniq -cもどき。

;; uniq-c.scm
(define (read-lines port)
  (let ((line (read-line port)))
    (if (eof-object? line)
      '()
      (cons line (read-lines port)))))

(define (uniq ls num)
  (cond
    ((null? ls) #f)  ;; do nothing
    ((null? (cdr ls))
     (format #t "~d\t~a\n" num (car ls)))
    ((equal? (car ls) (cadr ls))
     (uniq (cdr ls) (+ num 1)))
    (else
      (format #t "~d\t~a\n" num (car ls))
      (uniq (cdr ls) 1))))

(define (uniq-print ls)
  (uniq ls 1))

(uniq-print (read-lines (current-input-port)))
yz@ubuntu prog_exercises% cat test
abcde
abcde
fg
fg
fg
h
ijk
l
l
l
mn
yz@ubuntu prog_exercises% gosh uniq-c.scm < test
2       abcde
3       fg
1       h
1       ijk
3       l
1       mn

ついでに2回目の課題で作ってもらうsortも 標準入力を使うようにして、と。

正規表現の簡単な演習にもなるのでsort -nrも作って、と。

;; sort-nr.scm
(define (read-lines port)
  (let ((line (read-line port)))
    (if (eof-object? line)
      '()
      (cons line (read-lines port)))))

(for-each print
          (sort (read-lines (current-input-port))
                (lambda (a b)
                  (let ((num-a (rxmatch-substring (#/\d+/ a)))
                        (num-b (rxmatch-substring (#/\d+/ b))))
                    (> (string->number num-a) (string->number num-b))))))
yz@ubuntu prog_exercises% gosh uniq-c.scm < test | gosh sort-nr.scm
3       fg
3       l
2       abcde
1       h
1       ijk
1       mn

単語ごとにわけるプログラムも作って、と。

;; splitter.scm
(use srfi-13)

(define (read-lines port)
  (let ((line (read-line port)))
    (if (eof-object? line)
      '()
      (cons line (read-lines port)))))

(for-each (lambda (line)
            (for-each print
                      (let ((str (string-trim-both line)))
                        (if (string-null? str)
                          '()
                          (string-split str #/\s/)))))
          (read-lines (current-input-port)))
yz@ubuntu prog_exercises% echo 'I have a pen.' | gosh splitter.scm
I
have
a
pen.

これをパイプでつなぐ、と。

yz@ubuntu prog_exercises% gosh splitter.scm < slp.txt | gosh sort.scm | gosh uniq-c.scm | gosh sort-nr.scm | head
341     the
305     of
262     and
129     a
128     to
107     in
84      that
79      is
72      language
64      as

そうだ、Chasenを触ってもらうんだった。

yz@ubuntu prog_exercises% chasen how_to_become_a_hacker.txt | grep -v EOS | gosh sort.scm | gosh uniq-c.scm | gosh sort-nr.scm | head
437     、      、      、      記号-読点
411     。      。      。      記号-句点
393     は      ハ      は      助詞-係助詞
357     を      ヲ      を      助詞-格助詞-一般
350     の      ノ      の      助詞-連体化
304     に      ニ      に      助詞-格助詞-一般
208     て      テ      て      助詞-接続助詞
201     が      ガ      が      助詞-格助詞-一般
165     です    デス    です    助動詞  特殊・デス      基本形
162     ハッカー        ハッカー        ハッカー        名詞-一般

ふむ。入力文が1行1文になってないけど、それはあとでやっておくか……。 Schemeもちょっと慣れてきたw

そう言えば、オレがLinuxに惹かれた理由は日常の操作(コマンド)の中にもプログラミング的要素があって、 それが面白いし強力だと思ったからなんですよね。 授業でパイプでつなぐの見て、「こりゃすげぇ」と。この課題で伝わるかなぁ。

よく「Windowsでできることができなくなるのに(または不便になるのに)、なんでLinux?」とか言われるんだけど、 それは「Windowsに(簡単に)できないことがLinuxならできるから」なんだよね。 LinuxにできてWindowsにできないことを知らないで WindowsでやってることをそのままLinuxに移行しようと思っても、 キャラが違うんだから見劣りするのは当り前でLinux触る気なんて出ないだろうし。