ローカル変数スコープ(クラス、モジュー ル、メソッド定義の本体)における小文字で始まる識別子への最初 の代入はそのスコープに属するローカル変数の宣言になります。
ruby では最初の代入が変数宣言となるので、
広いスコープで使われた変数名を、
狭いスコープで別の変数の名前として使うことができない。
なぜなら、2回目の代入は(宣言なしの)単なる代入として処理されるから。
同名の変数を作るのがそもそも混乱のもとになるというのは一理あるので、
この仕様がひどいとはいえない。
「一度使われた名前は別の目的に使うことができない」という原則はそれなりに合理的だ。
しかし、
x = 10 [1,2,3].each { |x| } puts x
1
2
3
3
というように、ブロック引数内での変数さえも同じように振る舞うのはなんか嫌だ。
上記では、
|x|
の x が外の x だとみなされている。
これは合理的ではない。
もし、「xを1,2,3と次々と書き換える」ことを意図するなら
[1,2,3].each { |y| x=y }
と、ほとんど変わらない手間で、より明瞭に書けるからだ。
ruby-1.9 では
このようなブロック内の変数はブロックローカル変数として独立した変数になるようになった。
http://eigenclass.org/hiki/Changes+in+Ruby+1.9#l7
(2008-01-20T22:40:42+0900)
そもそも、ruby-1.8 のローカル変数スコープはメソッドごとにひとつづつしかなかった。
ruby-1.9 ではブロックローカル変数スコープが新設され、
ブロック引数はそのスコープを作ることになった。
……という理解が正しいようだ。
意外な単語がアナグラムだったりします。
thread
HATRED
reproduce
PROCEDURE
thousand
HANDOUTS
generate
TEENAGER
process
CORPSES
PROCESS
ruby -e'class String; def sort(); self.split(//).sort.join;end;end; dic={}; ARGV.each{|f| File.open(f).each{|x| x.chomp!; y=x.upcase.gsub(/\W/,""); sy = y.sort; dic[sy] ||= {}; dic[sy][y]=1;}}; STDIN.each{|x| puts((dic[x.upcase.gsub(/\W/,"").sort] || {""=>1}).keys)}' /usr/share/dict/{american,british}-english <(ruby -e'STDIN.each{|x| y=Regexp.new("<K>(.*?)</K><K>(.*?)</K>").match(x); if y then; puts y[2]; end}'< /usr/share/dict/jedict.sdic | kakasi -Ha |kakasi -Ka| iconv -f euc-jp -t utf-8)
引数にファイルを取る。
ファイルの形式は一行一単語。
単語はユーザーが入力する文字列と同じ文字セットと仮定する。
単語をソートしたときのハッシュ値を使って単語の同値類を作る。
2番目のシングルクォート以降にかかれている引数ファイルを、
ユーザーの環境に合わせて調整する。
あとでやる:
活用展開済みの形態素解析辞書を使って、
その辞書での最大アナグラムを見つける。
あとできづいた:
Programming Pearls で既出
sign | sort | squash
http://www.cs.bell-labs.com/cm/cs/pearls/s02.pdf
(2007-12-25T11:35:00+0900)
翻訳アナグラム問題 TransAnagram(A,B)
2つの文字列集合A,Bが与えられる。
a \in A, b \in B かつ、a は bのアナグラムであるような対
(a,b)をすべて出力せよ。
(あるいは、アナグラム同値類のうち、A,Bの両方にまたがるものを列挙せよ)
guitar
GUITAR
TAGURI
TAGIRU
chaos
CHAOS
SOCHA
pain
ANPI
tuesday
TUESDAY
YATSUDE
YATSUDE
heuristic
ICHIRETSU
HEURISTIC
hatena
ATHENA
(2007-12-25T11:37:57+0900)
Anagram(A) = TransAnagram(A,A)
(2007-12-25T11:39:20+0900)
TransAnagramの解1
A,Bを混ぜてAnagramを解く。
その出力のうち、A,Bの要素が混在している同値類が出力である。
(2007-12-25T11:45:10+0900)
練習問題
AnagramはP問題か?
(2007-12-25T15:16:56+0900)
See also:
http://www.notwork.org/~gotoken/mag/cmagazine/gokudo/8th/
文字を素数に置き換えて、ハッシュ値の計算を高速化する
http://blog.notdot.net/archives/38-Damn-Cool-Algorithms,-Part-3-Anagram-Trees.html
半順序関係である is-a-subanagram-of に関する列挙のための Anagram Trees
http://www.google.com/search?q=anagram%20algorithm
class Array def perm() if self.length <= 1 then [self] else a=self[1..-1].perm; c=[]; a.each { |x| 0.upto(x.length) { |y| c.push( (y==0 ? [] : x[0..y-1]) + [ self[0] ] + x[y..-1]) } } c.uniq end end end "123".split(//).perm.each{ |x| p x }
["1", "2", "3"]
["2", "1", "3"]
["2", "3", "1"]
["1", "3", "2"]
["3", "1", "2"]
["3", "2", "1"]
ruby 1.9 ではArrayクラスにある
(2007-12-18T22:27:03+0900)
C++だと std::next_permutation
http://cplusplus.com/reference/algorithm/next_permutation.html
#! /usr/bin/env ruby $KCODE='UTF8' require 'moji' DAKUON = Hash[*('ウヴカガキギクグケゲコゴサザシジスズセゼソゾタダチヂツヅテデトドハバヒビフブヘベホボ'.split //)] HANDAK = Hash[*('ハパヒピフプヘペホポ'.split //)] DAKUON_ORIGIN = DAKUON.keys.join HANDAK_ORIGIN = HANDAK.keys.join LATIN_ORIGIN0 = (0x01..0xFF).map{|x| x.chr}.join LATIN_ORIGIN = LATIN_ORIGIN0.sub(/\\/, '\\\\\\\\').sub(/-/, '\\-') LATIN_ZENKAKU = Moji.han_to_zen(LATIN_ORIGIN0) KATAKANA_ZENKAKU = 'ァィゥェォャュョッアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン゛゜' KATAKANA_HANKAKU = Moji.zen_to_han(KATAKANA_HANKAKU) while gets $_.tr!(KATAKANA_HANKAKU, KATAKANA_ZENKAKU) $_.gsub! /[(#{DAKUON_ORIGIN})]゛/, "#{DAKUON[$1]}" $_.gsub! /[(#{HANDAK_ORIGIN})]゜/, "#{HANDAK[$1]}" $_.tr! ' ', ' ' $_.tr!(LATIN_ORIGIN, LATIN_ZENKAKU) print $_ end
#! /usr/bin/env perl use utf8; use Readonly; use Encode; use Unicode::Japanese qw[unijp]; Readonly my %dakuon => map {$_} split //, 'ウヴカガキギクグケゲコゴサザシジスズセゼソゾタダチヂツヅテデトドハバヒビフブヘベホボ'; Readonly my %handakuon => map {$_} split //, 'ハパヒピフプヘペホポ'; Readonly my $dakuon_origin => join q{}, keys %dakuon; Readonly my $handakuon_origin => join q{}, keys %handakuon; Readonly my $keywordlist_encoding => q{utf-8}; while(<>){ $_ = decode_utf8 $_; chomp; trr/ァィゥェォャュョッアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン゙゚/ァィゥェォャュョッアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン゛゜/; s/([$dakuon_origin])゛/$dakuon{$1}/g; s/([$handakuon_origin])゜/$handakuon{$1}/g; tr/ \-~/ −〜/; tr[\x{01}-\x{FF}][\x{FEE1}-\x{FFDF}]; print encode_utf8 $_; print "\n"; }
ruby t.rb < <(head -n1000 x.txt) > /dev/null 0.20s user 0.00s system 82% cpu 0.251 total
perl t.pl < <(head -n1000 x.txt) > /dev/null 0.88s user 0.02s system 95% cpu 0.947 total
まとめ
- utf8フラグを立てたら負け
- オブジェクトを作ったら負け
<http://www.nesugi.net/hiki/?swig%A4%CE%BB%C8%A4%A4%CA%FD%A4%CE%A5%E1%A5%E2%BD%F1%A4%AD>
1. moduleにしたいプログラムのsource(*.cppとか)を持ってくる
2. cppファイル毎に*.iを書く ← これがswig語
3. swigコマンドで*.iを各スクリプト言語用のwrapper(c++で書かれてる)に変換
4. Makefile.PLやextconf.rbのような、スクリプト言語用のMakefileの元になるファイルを書く
5. 通常のモジュールと同じようにmakeする
<http://mono.kmc.gr.jp/~oxy/>
若き情報学者?
anthy の開発者の一人でもある。
$stdin [change]
$stdout, $stderr は、$defout, $deferr の別名になり $defout, $deferr は obsolete になりました
$stdin は、普通のグローバル変数となりました(STDINをリダイレクトする動作はなくなりました)
$defout や $deferr に代入を行うと警告がでます。 (注:1.6 に $deferr はありません) [ruby-dev:20961]
$stdin にオブジェクトを代入すると標準入力からの入力メソッド(gets 等) はそのオブジェクトにメソッドを投げます。 (リダイレクトしなくなった点を除けば、1.6 とそれほど違いはないようです)
1.6.8 では
$stdout = File.open("xxx", "w")
STDOUT.reopen("xxx", "w")
で、以降のプログラムでの標準出力への書き込みがファイル xxx にリダ
イレクトされていた。
1.8 では、前者が Ruby 内部でのリダイレクト、 後者が OSでのリダイレ
クトになり、
前者ではその文を実行するプロセスでのみリダイレクトされ、
後者は(今までどおり、 Cなどでもたぶん同じ)子プロセスまでリダイレク
トが波及する。