Hatena::Groupsicp

a666666の日記 このページをアンテナに追加 RSSフィード

2009-12-19

1.16. Soundex Matching

13:30 |  1.16. Soundex Matching - a666666の日記 を含むブックマーク はてなブックマーク -  1.16. Soundex Matching - a666666の日記  1.16. Soundex Matching - a666666の日記 のブックマークコメント

http://docstore.mik.ua/orelly/perl/cookbook/ch01_17.htm

英単語の「あいまい検索」を実装しろ、という話かな? Text::Soundex というモジュールを使えといってる。ハイ無理。いちおう Text::Soundex のソースを読んでみたけど XS 使ってた。アルゴリズムを真似て Gauche 版の text.soundex を作れたらすげーけど、とてもそんなレベルじゃないのでパス。いまはもっとレベル低いことからやる。

しかしパスとかできないとか増えてきたな。。

1.17. Program: fixstyle

14:30 |  1.17. Program: fixstyle - a666666の日記 を含むブックマーク はてなブックマーク -  1.17. Program: fixstyle - a666666の日記  1.17. Program: fixstyle - a666666の日記 のブックマークコメント

http://docstore.mik.ua/orelly/perl/cookbook/ch01_18.htm

だいぶ応用編になってきてる予感。。つらい。

Perl

#!/usr/bin/perl -w
# fixstyle - switch first set of <DATA> strings to second set
#   usage: $0 [-v] [files ...]
use strict;
my $verbose = (@ARGV && $ARGV[0] eq '-v' && shift);

if (@ARGV) {
    $^I = ".orig";          # preserve old files
} else {
    warn "$0: Reading from stdin\n" if -t STDIN;
}

my $code = "while (<>) {\n";
# read in config, build up code to eval
while (<DATA>) {
    chomp;
    my ($in, $out) = split /\s*=>\s*/;
    next unless $in && $out;
    $code .= "s{\\Q$in\\E}{$out}g";
    $code .= "&& printf STDERR qq($in => $out at \$ARGV line \$.\\n)" 
                                                        if $verbose;
    $code .= ";\n";
}
$code .= "print;\n}\n";

eval "{ $code } 1" || die;

__END__
analysed        => analyzed
built-in        => builtin
chastized       => chastised
commandline     => command-line
de-allocate     => deallocate
dropin          => drop-in
hardcode        => hard-code
meta-data       => metadata
multicharacter  => multi-character
multiway        => multi-way
non-empty       => nonempty
non-profit      => nonprofit
non-trappable   => nontrappable
pre-define      => predefine
preextend       => pre-extend
re-compiling    => recompiling
reenter         => re-enter
turnkey         => turn-key


とりあえず、 __DATA__ の単語リストを連想リストにすればよさそうだなと思って連想リストをつくるのを Gauche で書いてみようとしたけどどうにもうまくいかず。仕方ないので Perlフィルタを書いた。で、なんか単純に連想リストをキーで引いて値を返すだけのプログラムは書けた。

Gauche

(define alist
  '(
    (analysed . analyzed)
    (built-in . builtin)
    (chastized . chastised)
    (commandline . command-line)
    (de-allocate . deallocate)
    (dropin . drop-in)
    (hardcode . hard-code)
    (meta-data . metadata)
    (multicharacter . multi-character)
    (multiway . multi-way)
    (non-empty . nonempty)
    (non-profit . nonprofit)
    (non-trappable . nontrappable)
    (pre-define . predefine)
    (preextend . pre-extend)
    (re-compiling . recompiling)
    (reenter . re-enter)
    (turnkey . turn-key)))

(define (filter word alist)
  (cdr (assoc word alist)))

(filter 'analysed alist)

うーん、どうしようもない。 eval もあるから、文字列でコードを組み立ててどうたら、っていう問題の例どおりにすることもたぶんできるとおもうけど、まぁ、、先へ進もう。

1.18. Program: psgrep

15:26 |  1.18. Program: psgrep - a666666の日記 を含むブックマーク はてなブックマーク -  1.18. Program: psgrep - a666666の日記  1.18. Program: psgrep - a666666の日記 のブックマークコメント

http://docstore.mik.ua/orelly/perl/cookbook/ch01_19.htm

パス!!1 ・・・この次のページは二章だったので簡単そうなのから順次やります。。

2.1. Checking Whether a String Is a Valid Number

15:29 |  2.1. Checking Whether a String Is a Valid Number - a666666の日記 を含むブックマーク はてなブックマーク -  2.1. Checking Whether a String Is a Valid Number - a666666の日記  2.1. Checking Whether a String Is a Valid Number - a666666の日記 のブックマークコメント

http://docstore.mik.ua/orelly/perl/cookbook/ch02_02.htm

数字っぽい文字列かどうかを判定するという問題。正規表現でなんかいろいろやってる。しかし Perl でやるにしても何かモジュールあった気がするなぁ。

Perl

warn "has nondigits"        if     /\D/;
warn "not a natural number" unless /^\d+$/;             # rejects -3
warn "not an integer"       unless /^-?\d+$/;           # rejects +3
warn "not an integer"       unless /^[+-]?\d+$/;
warn "not a decimal number" unless /^-?\d+\.?\d*$/;     # rejects .2
warn "not a decimal number" unless /^-?(?:\d+(?:\.\d*)?|\.\d+)$/;
warn "not a C float"
       unless /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/;

で、 Gauche でやるならやっぱり組み込みの手続きがたくさんあるのでそれを使ったほうがよさそうだ。

Gauche

(number? x)

これだけ。。

2.2. Comparing Floating-Point Numbers

17:44 |  2.2. Comparing Floating-Point Numbers - a666666の日記 を含むブックマーク はてなブックマーク -  2.2. Comparing Floating-Point Numbers - a666666の日記  2.2. Comparing Floating-Point Numbers - a666666の日記 のブックマークコメント

http://docstore.mik.ua/orelly/perl/cookbook/ch02_03.htm

浮動小数点数の比較をしろ、ということのようなのだが・・・。 accuracy は精度って意味。小数点以下何桁目まで、同じ数字なのか、というのを調べるルーチンのようだ。

Perl

# equal(NUM1, NUM2, ACCURACY) : returns true if NUM1 and NUM2 are
# equal to ACCURACY number of decimal places

sub equal {
    my ($A, $B, $dp) = @_;

    return sprintf("%.${dp}g", $A) eq sprintf("%.${dp}g", $B);
  }

正直、精度とかさっぱりわからないので、

Gauche

(= x y)

ではだめなのですか?ってかんじです。。

=> 2.3 が解けた?のでこっちもやり直し。 2.3 で書いた myround を使った。 my= のなかで比較関数eq? を使ってしまって、 (eq? 3.14 3.14) が #f になるのはなんで?と思ってしまった(浮動小数点数は不正確数なので eq? で比較したら #f になるものらしい)

Gauche

(use math.const)

(define (myround x accurary)
  (let ((decimal (expt 10 accurary))) ; decimal => 10^accurary
    #?=(/ (round (* x decimal)) decimal)))

(define (my= x y accurary)
  (= (myround x accurary) (myround y accurary)))

(my= 3.14 pi 2)
; => #t
(my= 3.14 pi 3)
; => #f

2.3. Rounding Floating-Point Numbers

18:05 |  2.3. Rounding Floating-Point Numbers - a666666の日記 を含むブックマーク はてなブックマーク -  2.3. Rounding Floating-Point Numbers - a666666の日記  2.3. Rounding Floating-Point Numbers - a666666の日記 のブックマークコメント

http://docstore.mik.ua/orelly/perl/cookbook/ch02_04.htm

浮動小数点数を丸めなさい、という話。

うーん。。。わかりません。。。 => いやいやもうちょっと頑張れ俺、ということで書いてみました。

Perl

$a = 0.255;
$b = sprintf("%.2f", $a);
print "Unrounded: $a\nRounded: $b\n";
printf "Unrounded: $a\nRounded: %.2f\n", $a;

Unrounded: 0.255
Rounded: 0.26
Unrounded: 0.255
Rounded: 0.26

もはやコーディングの練習じゃなくてリファレンスマニュアルリーディングになりつつある。該当しそうな項目を読んでちょろっと一行くらいコードを書いてみるだけ(当然例題を解けるような分量ではない)

Gauche

(use math.const)

(define (myround x accurary)
  (let ((decimal (expt 10 accurary))) ; decimal => 10^accurary
    (/ (round (* x decimal)) decimal)))

pi
; => 3.141592653589793
(myround pi 7)
; => 3.1415927
(myround pi 3)
; => 3.142