http://jp.rubyist.net/?KansaiWorkshop24
行ってきましたRuby勉強会。2回目。
意気揚々と向かうも盛大に迷う。若さをアピールってわけでもないんですが、なんとなく歩いてみたら、曲がらなければいけないところで曲がらず、まっすぐ行ってしまい、人に聞いたら行き過ぎと言われて笑われました。
今回内容はRubyとかRailsもろって話はあまりなく、多方面の知識が得られたのが良かったかなと思います。RESTとかFlexの話は名前は知っているけどって状態だったのでおおまかにでも知識を得る事が出来たので良かったですし、iQubeの話はシステムの開発がどんな風に行われているのか知らなかったのでおもしろかったです。デモが見えなかったのが残念ですが。
そして、おまちかね初級者向けレッスン。
今回こそは全問解くぞと意気込んでいたのですが、やっぱり駄目。
自分がいかにあいまいな知識しか持ってないか思い知らされました。
解いたので、さらします。
第一問、英文の解析
文字数、単語数、行数、文字別の出現頻度、単語の出現頻度をカウントします。
puts `wc text.txt`
1行で書けました。すばらしい。(出現頻度無視)
・・・冗談です。ほんとはこっち。
count = { :line => 0, :char => 0, :word => 0, } frequency = { :linefreq => Hash.new {|h, k| h[k] = 0 }, :wordfreq => Hash.new {|h, k| h[k] = 0 }, } count[:line] = IO.readlines("text.txt").each {|line| count[:char] += line.split(//).each {|c| frequency[:linefreq][c] += 1 if c =~ /\w/ }.length count[:word] += line.split(' ').each {|w| frequency[:wordfreq][w] += 1 if w =~ /\A\w+\Z/ }.length }.length count.each {|k, v| puts "#{k}: #{v}" } frequency.each do |k, v| puts "------------------\n" + "#{k}\n" + "------------------" v.sort.each do |k, v| puts "#{k}: #{v}" end end
なんだかかぶってる箇所が多くてもうちょういDRYでスマートなコードにしたいんですが、今の限界。
出力が面倒くさかったので、countとfrequencyで分けて集計してます。
第二問、ログの解析
汎用的に書こうとして挫折した感じ。
Macユーザもあきらめました。
英語が間違ってそうで心配。
#追記:Livedoor FeedFetcherをsplit(' ')してる。これは誤差です。
require 'date' class LogAnalyser LOG = /\A([^\s]+)\s([^\s]+)\s([^\s]+)\s\[(.+)\]\s\"([^"]+)\"\s((?:\d+|-)\s(?:\d+|-))\s\"([^"]*)\"\s\"([^"]*)\"/ def initialize(file = 'access.log') @log = File.open(file, 'rb').map {|line| LOG =~ line [$1, $2, $3, $4, $5.to_s.split(' '), $6, $7, $8].flatten } end def count_for(type, keyword) begin @log.inject(0) {|r, v| r += 1 if v[number_of(type)] =~ Regexp.new(keyword); r } rescue $stderr << 'error' exit end end def best_access_wday week = ['Sunday', 'Monday', 'Tuesday' 'Wednesday', 'Thursday', 'Friday', 'Saturday'] rank = Hash.new {|h, k| h[k] = 0 } get_date_list.each {|date| rank[date.wday] += 1 } week[rank.max {|a, b| a[1] <=> b[1] }[0]] end # for browser only def ranking(type) return unless type == :browser count(type).sort_by {|k, v| -v }[0..9] end private def count(type) begin rank = Hash.new {|h, k| h[k] = 0 } @log.each do |l| b = l[number_of(type)].split(' ')[0].split('(')[0].split(';')[0] rank[b] += 1 end rank rescue $stderr << 'error' exit end end def get_date_list @log.map {|l| Date.parse l[number_of(:date)] } end def number_of(type) case type when :ipaddress ; 0 when :user ; 2 when :date ; 3 when :method ; 4 when :uri ; 5 when :protocol ; 6 when :status ; 7 when :referer ; 8 when :browser ; 9 else raise end end end lana = LogAnalyser.new puts "Access for 'index.php': #{lana.count_for(:uri, 'index.php')}" puts "First access day by Mac user: I can't analyse..." puts "Access from Google: #{lana.count_for(:referer, 'google')}" puts "Best acsess day of week: #{lana.best_access_wday}" puts "Top 10 browsers:" lana.ranking(:browser).each_with_index do |(name, count), i| puts "#{(i+1).to_s.rjust(2)} #{name.ljust(22)}: #{count}" end