Posted by yatsu Sun, 05 Mar 2006 16:36:57 GMT
FreeML メッセージ RubyCocoa/AEOSA ML - 325
RubyCocoaをMac OS Xに含めることが検討されていているらしい。
これに関する話しをMLやblogなど公の 場でしてもいいということなので、書いてみた。
Posted by yatsu Sun, 05 Mar 2006 16:36:57 GMT
FreeML メッセージ RubyCocoa/AEOSA ML - 325
RubyCocoaをMac OS Xに含めることが検討されていているらしい。
これに関する話しをMLやblogなど公の 場でしてもいいということなので、書いてみた。
Posted by yatsu Wed, 30 Nov 2005 21:03:19 GMT
Auto-fill your reverse migrations で紹介されている Reverse_Migration.tmbundle を使うと、self.up の中身から、その逆のことをする self.down を生成してくれるらしい。
Posted by yatsu Fri, 30 Sep 2005 15:40:00 GMT
PragDave - More Beta Books on the Way によると、『Agile Web Development with Rails』と同じ方式で、以下2冊のベータ版がリリースされるとのこと。
どちらも読みたい。
Posted by yatsu Thu, 08 Sep 2005 22:44:00 GMT
2007-06-04 追記 ruby-pytstはこちら → yatsu.info : ruby-pytstをRubyForgeに登録
はてなキーワード付与の速度問題は、LesserWikiの速度問題と同じっぽい :)
で、僕が考えたのもAho-Corasick法(AC法)だったが、自分でアルゴリズムを書くのが面倒だったので、pytstというPython用TSTライブラリをRubyに移植してみた(とりあえずruby-tstと名付けた)。 名前のとおり、Trie構造はTST(Ternary Search Trie)を使用している。
pytstはC++で実装されていて、SWIGでPython対応しているが、ruby-tstはCで書き直した。
/usr/share/dict/wordsの23万語をキーワードにして、Google Newsの記事中の単語を一括置換してみたところ、かなり速いパフォーマンスを発揮した。
TST構造はRubyのハッシュのようにも使用できる。
t = TST.new
t[:test] = "TEST"
p t[:test]
検索する場合は
require 'tst'
t = TST.new
t["abc"] = "abc"
t["abcdef"] = "abcdef"
t["abcdefgh"] = "abcdefgh"
t["01"] = "01"
t["02"] = "02"
%w[abc 01 abc01 abc---01 abcdef---abc--01--abcdef--abc].each do |str|
t.scan(str) {|s, d, v| print "('#{s}' #{d} '#{v}') "}
puts
end
これを実行すると、こうなる。
('abc' 3 'abc')
('01' 2 '01')
('abc' 3 'abc') ('01' 2 '01')
('abc' 3 'abc') ('---' -3 '') ('01' 2 '01')
('abcdef' 6 'abcdef') ('---' -3 '') ('abc' 3 'abc') ('--' -2 '') ('01' 2 '01')
('--' -2 '') ('abcdef' 6 'abcdef') ('--' -2 '') ('abc' 3 'abc')
ブロックを受け取って一括置換してくれるreplaceメソッドもあるが、面倒なので(そればっかりだな)省略。
Marshalにも対応したが、Rubyの型を使ってmarshal_dump, marshal_load対応したためか、遅い。
その他の問題点は、ときどき落ちること(w
メモリ破壊していると思われ……。
2週間ほどほったらかしにしているので、そろそろ修正して公開したいところ。
AC法については北研二、津田和彦、獅々堀正幹『情報検索アルゴリズム』、TSTについてはセジウィック『アルゴリズムC・新版』(旧版には載っていないので注意)がわかりやすい。
Posted by yatsu Thu, 25 Aug 2005 03:16:00 GMT
Markdown Web Dingusで -> と書いてSmartyPants変換をすると、→(→)になってくれる。
ところがRubyPantsではこの変換はやってくれないようだ。
そこでSmartyPantsのページを確認してみたのだが、それらしい記述は見つからなかった。バージョン1.5.1のソースを眺めてみたが、それらしいコードもないようだ。
もう少し調べてみよう。
Posted by yatsu Thu, 25 Aug 2005 03:09:00 GMT
BlueClothはバッククォートで囲まれた領域をcodeに変換してくれるのだが、閉じていない(対になっていない)ときにエラーになってしまうという問題があるようだ。
Wikiでエラーになってしまうと二度とWeb上で書き直すことができなくなってしまうので対応を考えなければならない。
Posted by yatsu Sat, 06 Aug 2005 02:22:00 GMT
naoyaのはてなダイアリー – HTML::TagCloud で紹介されているように、PerlにはTagCloud (はてなブックマークの右側に出てくるタグ一覧みたいなやつ) を生成する HTML::TagCloud というものがありますが、Rubyにはそれに相当するものがなさそうだったので、作ってみました。 アルゴリズムはHTML::TagCloudとまったく同じです。
Rubyライセンスということにしておきますので、ご自由にお使いください。
# Author: Masaki Yatsu <yatsu@yatsu.info>
class TagCloud
def initialize
@counts = Hash.new
@urls = Hash.new
end
def add(tag, url, count)
@counts[tag] = count
@urls[tag] = url
end
def css
text = ""
for level in 0..24
font = 12 + level
text << "span.tagcloud#{level} {font-size: #{font}px;}\n"
text << "span.tagcloud#{level} a {text-decoration: none;}\n"
end
text
end
def html(limit = nil)
tags = @counts.sort_by {|a, b| b }.reverse.map {|a, b| a }
tags = tags[0..limit-1] if limit
if tags.empty?
return ""
elsif tags.size == 1
tag = tags[0]
url = @urls[tag]
return %{<span class="tagcloud24"><a href="#{url}">#{tag}</a></span>\n}
end
min = Math.sqrt(@counts[tags.last])
max = Math.sqrt(@counts[tags.first])
factor = 0
# special case all tags having the same count
if max - min == 0
min = min - 24
factor = 1
else
factor = 24 / (max - min)
end
html = ""
tags.sort.each do |tag|
count = @counts[tag]
url = @urls[tag]
level = ((Math.sqrt(count) - min) * factor).to_i
html << %{<span class="tagcloud#{level}"><a href="#{url}">#{tag}</a></span>\n}
end
html
end
def html_and_css(limit = nil)
"<style>\n#{self.css}</style>\n#{self.html(limit)}"
end
end
サンプルは naoyaのはてなダイアリー – HTML::TagCloud をまねて、以下のようにしました。
#!/usr/bin/ruby
require 'tagcloud'
tags = [
{ :tag => 'blog', :count => 20 },
{ :tag => 'ajax', :count => 10 },
{ :tag => 'mysql', :count => 5 },
{ :tag => 'hatena', :count => 12 },
{ :tag => 'bookmark', :count => 30 },
{ :tag => 'rss', :count => 1 },
{ :tag => 'atom', :count => 2 },
{ :tag => 'misc', :count => 10 },
{ :tag => 'javascript', :count => 11 },
{ :tag => 'xml', :count => 6 },
{ :tag => 'perl', :count => 32 },
]
cloud = TagCloud.new
tags.each do |t|
cloud.add(t[:tag], "http://<your.domain>/#{t[:tag]}/", t[:count])
end
print cloud.html_and_css(20)
出力は以下のように、HTML::TagCloudと同じになります。
<style>
span.tagcloud0 {font-size: 12px;}
span.tagcloud0 a {text-decoration: none;}
span.tagcloud1 {font-size: 13px;}
span.tagcloud1 a {text-decoration: none;}
span.tagcloud2 {font-size: 14px;}
span.tagcloud2 a {text-decoration: none;}
span.tagcloud3 {font-size: 15px;}
...
</style>
<span class="tagcloud11"><a href="http://<your.domain>/ajax/">ajax</a></span>
<span class="tagcloud2"><a href="http://<your.domain>/atom/">atom</a></span>
<span class="tagcloud17"><a href="http://<your.domain>/blog/">blog</a></span>
...
さて、こいつを LesserWiki に組み込もうか。
Older posts: 1 2