Skip to content

Instantly share code, notes, and snippets.

@syntacticsugar
Forked from bil-bas/rubymas.rb
Created June 6, 2013 05:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save syntacticsugar/5719569 to your computer and use it in GitHub Desktop.
Save syntacticsugar/5719569 to your computer and use it in GitHub Desktop.
class Fixnum
def ordinal
%w[first second third fourth fifth sixth seventh eighth ninth tenth eleventh twelfth][self - 1]
end
# Use #to_word rather than #to_s, so it doesn't break any other printing of numbers.
def to_word
%w[one two three four five six seven eight nine ten eleven twelve][self - 1]
end
end
class Rubymas
include Enumerable
GIFTS = {
1 => 'a garbage collector with an embarrassing stutter',
2 => '#ruby slippers',
3 => 'hash rockets => => =>',
4 => 'unplayed games',
5 => 'Sinatra songs',
6 => 'segfaulting extensions',
7 => 'pragmatic hackers',
8 => 'lucky stiffs',
9 => 'scintillating beardies',
10 => 'leet Macbooks',
11 => 'gazillion tests',
12 => 'Rails hipsters',
}
# @param algorithm [:functional, :functionalish, :recursive] Algorithm used to create list of gifts.
def initialize(algorithm)
# Map the name of the algorithm to the appropriate method to use.
list_of_gifts_method = "list_of_gifts_#{algorithm}"
if respond_to? list_of_gifts_method
@list_of_gifts = method list_of_gifts_method
else
raise ArgumentError, "Algorithm, #{algorithm.inspect} not supported"
end
end
# Allow us to iterate through the song, with the Enumerable methods,
# such as #each, #map, #reverse_each and #to_a.
def each
(1..12).each {|day| yield chorus day }
end
# Output as a full song, with each chorus separated by an empty line.
def to_s
to_a.join "\n\n"
end
# Let's stop naughty girls from peeking at their gifts too early!
protected
def gift(day)
# Memoise it because it is hip and we have hips.
# Completely pointless, but 'memoisation' is fun to type and fun to say!
# Don't let nasty spell-checkers make you 'memorise' it though D:
@gifts ||= Hash.new do |hash, key|
hash[key] = case key
when 1 then GIFTS[1]
when 2..12 then "#{key.to_word} #{GIFTS[key]}"
else raise 'an exquisite eyebrow'
end
end
@gifts[day]
end
def list_of_gifts_recursive(day)
# Put the gifts in a big pile, ready for the courier service.
case day
when 1 then gift 1
# Could recurse this next case, but it is as no simpler than just doing it
# this way (list_of_gifts(1) vs. gift(1)).
when 2 then "#{gift 2} and #{gift 1}"
when 3..12 then "#{gift(day)}, #{list_of_gifts_recursive(day - 1)}"
end
end
def list_of_gifts_functionalish(day)
# Put all but the last gift in a big pile, ready for the courier service.
gifts = day.downto(2).map(&method(:gift)).join ', '
# And it was looking so functional...
gifts << ' and ' unless day == 1
gifts << gift(1)
end
def list_of_gifts_functional(day)
# Put the gifts in a big pile, ready for the courier service.
# Lamdas are cool too. They are so cute and cuddly and fluffy.
separator = lambda do |i|
case i
when 3..12 then ', '
when 2 then ' and '
when 1 then ''
end
end
# As we know, #injecting gives you cooties, so stay in school #with_object!
day.downto(1).with_object('') do |current_day, str|
(str << gift(current_day)) << separator[current_day]
end
end
def chorus(day)
"On the #{day.ordinal} day of Rubymas, my true love gave to me: #{@list_of_gifts[day]}."
end
end
# Use three different algorithms to generate identical output. This is the way
# they do it in the space shuttle, you know. Ironically, it is 'redundancy' like
# this that keeps people in work!
[:recursive, :functionalish, :functional].each do |algorithm|
puts '-' * 60
puts "Now let's be a good little #{algorithm} Al Gore Rhythm!"
puts
puts Rubymas.new(algorithm)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment