J
James Edward Gray II
I've mentioned it before, but if you don't know Perl programmers
maintain a "Quiz of the Week". If you want to know more, the page is
here:
http://perl.plover.com/qotw/
This week's Regular Quiz (there also an Expert Quiz) came out last
night. The curious can read it here:
http://article.gmane.org/gmane.comp.lang.perl.qotw.quiz-of-the-week/105
*** SPOILER WARNING ***
Stop reading this message if you read the Quiz and would like to solve
it yourself, without seeing a solution first.
Okay, now to my point, finally...
I've solved the Quiz in Ruby. If you've seen my earlier posts, you
know I'm brand new to Ruby. I've spent the last week and a half
learning it and this is really my first attempt to put it to use.
If any of you can spare the time, I would appreciate an honest review
of the code I generated. I'm interested in any opinions you might have
about constructs, style, whatever. I'm especially looking for things
I'm handling in a non-Ruby fashion. Break my bad habits before they
take hold... <laughs>
Thanks in advance for sharing your time. Here's the code:
#!/usr/bin/ruby -w
require "getoptlong"
class Event
attr_reader :category, :day, :month, :year, :name
def Event.parse( string, cat )
if string =~ /^\s*(?\d+)\/)?(\d+)(?:\/(\d+))?\s+(.+?)\s*$/
return Event.new( cat, $4, $2, $1, $3 )
else
return
end
end
def initialize( cat, event, dd, mm = nil, yyyy = nil )
@category = cat
@name = event
@day = dd.to_i
@month = mm.to_i
@year = yyyy.to_i
end
def <=>( other )
if not year.zero? and not other.year.zero? and year != other.year
return year <=> other.year
elsif not month.zero? and not other.month.zero? and month !=
other.month
return month <=> other.month
else
return day <=> other.day
end
end
def between?( min, max )
times = [ min ]
until times[-1].year == max.year and times[-1].month == max.month and
times[-1].day == max.day
times << times[-1] + (60 * 60 * 24)
end
result = times.find do | time |
(year == 0 or year == time.year) and
(month == 0 or month == time.month) and
day == time.day
end
if result
times.index result
else
return
end
end
def date
date = day.to_s
unless month.zero?
date = month.to_s + "/" + date
end
unless year.zero?
date += "/" + year.to_s
end
return date
end
end
delta = 7
GetoptLong.new( [ "-n", GetoptLong::REQUIRED_ARGUMENT ] ).each do |
opt, arg |
delta = arg.to_i if opt == "-n"
end
NOW = Time.now
LIMIT = NOW + (delta * 24 * 60 * 60)
OFFSETS = [ " ===>", " -->", " -->", " -->", "-->", "->", ">", "" ]
DIR = File.join ENV["HOME"], '.upcoming';
events = { }
Dir.foreach DIR do | file_name |
next if file_name =~ /^\./
File.open File.join( DIR, file_name ) do | file |
while line = file.gets
e = Event.parse line, file_name
if e
events[file_name] = [ ] unless events.key? file_name
events[file_name] << e
end
end
end
end
puts
events.each do | key, value |
next unless value.find { | e | e.between? NOW, LIMIT }
puts key
value.sort.each do | e |
offset = e.between? NOW, LIMIT
next unless offset
case offset
when 0..7
printf "%-7s ", OFFSETS[offset]
else
printf "%-7s ", "(" + offset.to_s + ")"
end
printf "%-10s %s\n", e.date, e.name
end
puts
end
__END__
James Edward Gray II
maintain a "Quiz of the Week". If you want to know more, the page is
here:
http://perl.plover.com/qotw/
This week's Regular Quiz (there also an Expert Quiz) came out last
night. The curious can read it here:
http://article.gmane.org/gmane.comp.lang.perl.qotw.quiz-of-the-week/105
*** SPOILER WARNING ***
Stop reading this message if you read the Quiz and would like to solve
it yourself, without seeing a solution first.
Okay, now to my point, finally...
I've solved the Quiz in Ruby. If you've seen my earlier posts, you
know I'm brand new to Ruby. I've spent the last week and a half
learning it and this is really my first attempt to put it to use.
If any of you can spare the time, I would appreciate an honest review
of the code I generated. I'm interested in any opinions you might have
about constructs, style, whatever. I'm especially looking for things
I'm handling in a non-Ruby fashion. Break my bad habits before they
take hold... <laughs>
Thanks in advance for sharing your time. Here's the code:
#!/usr/bin/ruby -w
require "getoptlong"
class Event
attr_reader :category, :day, :month, :year, :name
def Event.parse( string, cat )
if string =~ /^\s*(?\d+)\/)?(\d+)(?:\/(\d+))?\s+(.+?)\s*$/
return Event.new( cat, $4, $2, $1, $3 )
else
return
end
end
def initialize( cat, event, dd, mm = nil, yyyy = nil )
@category = cat
@name = event
@day = dd.to_i
@month = mm.to_i
@year = yyyy.to_i
end
def <=>( other )
if not year.zero? and not other.year.zero? and year != other.year
return year <=> other.year
elsif not month.zero? and not other.month.zero? and month !=
other.month
return month <=> other.month
else
return day <=> other.day
end
end
def between?( min, max )
times = [ min ]
until times[-1].year == max.year and times[-1].month == max.month and
times[-1].day == max.day
times << times[-1] + (60 * 60 * 24)
end
result = times.find do | time |
(year == 0 or year == time.year) and
(month == 0 or month == time.month) and
day == time.day
end
if result
times.index result
else
return
end
end
def date
date = day.to_s
unless month.zero?
date = month.to_s + "/" + date
end
unless year.zero?
date += "/" + year.to_s
end
return date
end
end
delta = 7
GetoptLong.new( [ "-n", GetoptLong::REQUIRED_ARGUMENT ] ).each do |
opt, arg |
delta = arg.to_i if opt == "-n"
end
NOW = Time.now
LIMIT = NOW + (delta * 24 * 60 * 60)
OFFSETS = [ " ===>", " -->", " -->", " -->", "-->", "->", ">", "" ]
DIR = File.join ENV["HOME"], '.upcoming';
events = { }
Dir.foreach DIR do | file_name |
next if file_name =~ /^\./
File.open File.join( DIR, file_name ) do | file |
while line = file.gets
e = Event.parse line, file_name
if e
events[file_name] = [ ] unless events.key? file_name
events[file_name] << e
end
end
end
end
puts
events.each do | key, value |
next unless value.find { | e | e.between? NOW, LIMIT }
puts key
value.sort.each do | e |
offset = e.between? NOW, LIMIT
next unless offset
case offset
when 0..7
printf "%-7s ", OFFSETS[offset]
else
printf "%-7s ", "(" + offset.to_s + ")"
end
printf "%-10s %s\n", e.date, e.name
end
puts
end
__END__
James Edward Gray II