2007-05-03
■ [scheme] SICPはじめました
http://sicp.g.hatena.ne.jp/yhara/
なんとなく勢いでSICP(日本語版)を買ってしまったので、淡々と問題を解いていこうかなと思います。 ユニットテストが書けそうなものはgauche.testを使ってテストファーストで。
■ [ruby] Ruby/AnarchyGolf
Hpricotを使って、AnarchyGolfのスクレイパを書いてみました。
使用例。
yhara@meteor:~/HTML/anagol % irb -r lib/anagol.rb
>> anagol = AnarchyGolf.new
=> #<AnarchyGolf:0x2aaaac15e9f0 @html={}>
>> langs = anagol.languages
=> [#<struct AnarchyGolf::Language name="Ruby", short_name="rb">,
(中略),
#<struct AnarchyGolf::Language name="x86", short_name="out">]
>> probs = anagol.problems
=> [#<AnarchyGolf::Problem:0x2aaaacf21600 @name="hello world">,
(中略),
#<AnarchyGolf::Problem:0x2aaaacf1dd70 @name="128 bits">]
>> hw = probs.first
=> #<AnarchyGolf::Problem:0x2aaaacf21600 @name="hello world">
>> hw.name
=> "hello world"
>> hw.url
=> "http://golf.shinh.org/p.rb?hello+world"
>> hw.description
=> "say "Hello, world!""
>> hw.deadline
=> nil
>> hw.revealed?
=> false
>> hw.ranking["Ruby"].first
=> #<struct AnarchyGolf::Problem::Score rank=1, lang="Ruby", user="eban", size=19, score=nil, time=0.1226, date="07/01/30 16:37:51", stat="?B / ?B / ?B">
>> hw.language_ranking.first
=> #<struct AnarchyGolf::Problem::Score rank=1, lang="PHP", user="konbu", size=13, score=10000, time=nil, date=nil, stat=nil>
>> hw.has_language?("Befunge")
=> true
problemsを呼んだときに各問題に対応するProblemのインスタンスが生成される……のですが、 problemsを呼ぶだけで全問題のURLにアクセスするとサーバに負荷がかかりすぎるので、 Problem#descriptionやProblem#rankingといったプロパティは「実際にアクセスされたときに初めて値を取りに行く」 ようになっています。
実装はこんな感じ。
module CachedAttribute
def cached_attr_reader(*syms)
syms.each do |attr|
module_eval <<-EOD
def #{attr}
if defined? @#{attr}
@#{attr}
else
@#{attr} = update_#{attr}
end
end
EOD
end
end
end
class AnarchyGolf
class Problem
extend CachedAttribute
cached_attr_reader :description, :deadline, :revealed
cached_attr_reader :ranking, :language_ranking
...
def update_ranking
# 最初にProblem#rankingが呼ばれたときだけ実行される
さて、何がやりたかったかというと、UnlambdaとかErlangとかマイナーな言語の簡単なサンプルコードが欲しかったのでした。 *1 とりあえずanagol tableを作って目的は達成された…のですが、 実際にコードを見たところでgolfされてるから意味不明という罠が。しまった!
*1 最近の問題は一定時間で回答が公開されるようになってたりする
[ツッコミを入れる]