Skip to content

Instantly share code, notes, and snippets.

@RBangel
Last active August 29, 2015 14:08
Show Gist options
  • Select an option

  • Save RBangel/1a2052af9297bf615bc3 to your computer and use it in GitHub Desktop.

Select an option

Save RBangel/1a2052af9297bf615bc3 to your computer and use it in GitHub Desktop.
# Functional version
count = ->(b) { if b > 0 then "#{b}" else "no more" end }
plural = ->(b) { if b == 1 then "" else "s" end }
pronoun = ->(b) { if b == 1 then "it" else "one" end }
wall = -> (d) { if d then " on the wall" else "" end }
$bottles = ->(b, d) { "#{count.call(b)} bottle#{plural.call(b)} of beer#{wall.call(d)}" }
$take_one = ->(b) { "Take #{pronoun.call(b)} down and pass it around" }
$take_none = ->() { "Go to the store and buy some more" }
class Bottles
def song
verses(99, 0)
end
def verses(starting, ending)
verses_array(starting, ending).reduce("") { |r, v| r + verse(v) + "\n" }.chomp
end
def verse(b)
look = ->(b) { "#{$bottles.call(b, true)}, #{$bottles.call(b, false)}." }
take = ->(b) do
if b > 0 then
"#{$take_one.call(b)}, #{$bottles.call(b - 1, true)}."
else
"#{$take_none.call}, #{$bottles.call(99, true)}."
end
end
"#{look.call(b).capitalize}\n#{take.call(b).capitalize}\n"
end
end
def verses_array(starting, ending)
Range.new(ending, starting).to_a.reverse
end
class Bottles
def song
verses(99, 0)
end
def verses(starting, ending)
response = ""
while starting >= ending
response = response + self.verse(starting)
response += "\n" if starting > ending
starting = starting - 1
end
response
end
def verse(num_bottles)
if num_bottles == 0
return "No more bottles of beer on the wall, no more bottles of beer.\n" +
"Go to the store and buy some more, 99 bottles of beer on the wall.\n"
end
curr_num = "#{num_bottles} #{num_bottles > 1 ? "bottles" : "bottle" }"
new_num_bottles = num_bottles - 1
if new_num_bottles > 1
new_num = "#{new_num_bottles} bottles"
elsif new_num_bottles == 1
new_num = "1 bottle"
else
new_num = "no more bottles"
end
"#{curr_num} of beer on the wall, #{curr_num} of beer.\n" +
"Take #{num_bottles > 1 ? "one" : "it"} down and pass it around, " +
"#{new_num} of beer on the wall.\n"
end
end
class Bottles
def song
verses(99, 0)
end
def verses(starting, ending)
return verse(ending) if starting == ending
verse(starting) + "\n" + verses(starting - 1, ending)
end
def verse(bottles)
wall = Wall.new(bottles)
"#{wall.bottles.capitalize} on the wall, #{wall.bottles}.\n" +
"#{wall.take_bottle.capitalize}, #{wall.bottles} on the wall.\n"
end
end
class Wall
def initialize(bottles)
@bottles = bottles
end
def bottles
if @bottles > 1 then
"#{@bottles} bottles"
elsif @bottles == 1
"#{@bottles} bottle"
else
"no more bottles"
end + " of beer"
end
def take_bottle
term = @bottles > 1 ? "one" : "it"
@bottles = @bottles - 1
if @bottles >= 0 then
"take #{term} down and pass it around"
else
@bottles = 99
"Go to the store and buy some more"
end
end
end
@McPolemic
Copy link
Copy Markdown

A couple of thoughts:

  1. As a rule, I'd prefer no newlines in the middle of strings. Use heredocs to make it a bit more readable.
  2. I'm not quite sure what you're going for in proc_bottles, since I don't see you using Procs.
  3. For if/elses that have three or more branches, I prefer case/when.
  4. verses in proc_bottles.rb feels like it could be replaced with map and Array#join.

Rubocop found some other problems (just to nitpick)
4. Instead of adding strings, I'd use \.
5. Instead of starting = starting - 1, use -=

Overall, I prefer oop_bottles.rb. It has a nice separation of concerns and concise, isolated, short methods. proc_bottles.rb feels like it's all over the place, functionality-wise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment