fizzbuzzをやってみた - うんたらかんたらRuby - Rubyist
anarchy golf - FizzBuzz
glofでは、67位なんだけど早さでは何位なんだろうかと思って
scrapeしてsortしてみようと思い立った。
ここら辺(Ruby Scraping - FrontPage)をみながら
「xpathとかcssセレクタとかを簡単に扱えるらしい。」ということで
Nokogiri(tenderlove's nokogiri at master — GitHub)をインストールしてみることに。
インストール
gem install nokogiri
で簡単に入れれるらしい。
Building native extensions. This could take a while... ERROR: While executing gem ... (Gem::Installer::ExtensionBuildError) ERROR: Failed to build gem native extension.
でもエラー。。
gemを更新して再度やったらうまくいった。
gem update --system
早速使ってみる
xpathで簡単にデータが取得できるのはわかったけど、
このhtml(anarchy golf - FizzBuzz)には
idとかclassとかが適切に設定されていないので
Rubyの結果だけを抜き出せるようなxpathが書けない。
htmlの構造は↓みたいな感じになってる。
html
body
a Ruby(言語名)....
table Rubyの結果
a Perl(言語名)....
table Perlの結果
・
・
・
悩んだ結果、「言語名のaタグ」の後に「結果のtableタグ」が必ずくるので
それぞれ別々の配列に取得して、使う時に同じindexを使えば
欲しい言語の結果が取り出せそう。
書いてみた
require 'rubygems' require 'nokogiri' require 'open-uri' abort('no argument err.') if ARGV.size == 0 doc = Nokogiri::HTML(open('http://golf.shinh.org/p.rb?FizzBuzz#Ruby')) #言語名を配列にセット prog_names = [] doc.xpath('/html/body/h3/a[@href]').each do |nsa| href = "" href = nsa.get_attribute("href") if href =~ /\/l\.rb\?.*/ prog_names << nsa.inner_text end end #tableタグを配列にセット #tables最後のtable要素は「Language Ranking」が含まれる。(言語名より1つ多い) tables = [] tables = doc.xpath('/html/body/table') rank_info = Hash.new prog_names.each_with_index do |prog, i| if ARGV[0].upcase == prog.upcase p prog tables[i].xpath('tr').each do |tr| user = tr.xpath('td[2]').inner_text time = tr.xpath('td[4]').inner_text if user != "" && time != "" rank_info[user] = time end end end end puts "Rank User Time" puts "------------------------------" rank_info.sort_by {|key, val| val}.each_with_index{|x, n| puts "#{n + 1} #{x[0]} #{x[1]}"}
引数で指定した言語の結果を早さ順に並べ替えます。
結果
$ ruby noko.rb ruby "Ruby" Rank User Time ------------------------------ 1 leonid (alnum) 0.0003 2 Duane Bailey 0.0071 3 Matthew 0.0118 4 crazyjimbo 0.0171 5 khtokage 0.0197 6 yuya 0.0296 7 rawwell 0.0302 8 flagitious(alnum) 0.0344 9 rickrickrick 0.0355 10 shrapnel 0.0373 11 rochefort 0.0373 12 Steve Cooper 0.0432 13 mokos 0.0487 14 lw 0.0491 15 smly 0.0492 以下略
なんとか、11位(同順で10位。ここは考慮できてない)。
疑問点
今回は、sortにhashを利用したけど、構造体の配列みたいなので本当はやりたい。
でもよくわかんない(2次元配列とかのソートが)。
user名でソートとかを簡単にするには、多次元配列のソートを書かないといけないのかな。
簡単にできる方法はないのかな。