patternrubyMajor
99 bottles of beer on the wall
Viewed 0 times
wallthebottlesbeer
Problem
I'm super new to this so please be nice. I tried solving Chris Pine's challenge to print the entire lyrics to 99 bottles of beer on the wall. This seems to work, but is there a better/more efficient way to do it? Just want to learn how to improve it if I can.
var1 = 99
loop do
puts (var1.to_s) + ' bottles of beer on the wall, ' + (var1.to_s) + ' bottles of beer, '
puts 'take one down, pass it around, ' + ((var1 - 1).to_s) + ' bottles of beer on the wall.'
var1 = (var1 - 1)
break if var1 == 1
endSolution
In any programming language you should always use meaningful names for your variables, functions, methods, and whatever else you need to assign a name.
In your case,
Secondly, in Ruby, you rarely need to use a plain
A simple way to do this in Ruby is to say:
The
And speaking of printing, you're making things difficult for yourself by not using string interpolation.
If you use double quotes instead of single quotes, you can use
Note that
The above code is pretty much equivalent to your current code, except that it prints a blank line between verses. And the fact that it prints 99 verses - you're actually only printing 98 verses in your version.
... However, it's printing wrong lyrics. Grammatically incorrect lyrics, at any rate.
Most verses do indeed go like this:
X bottles of beer on the wall, X bottles of beer.
Take one down and pass it around, (X-1) bottles of beer on the wall.
where X is whatever number of bottles we have left. (Note, by the way, how much this looks like the Ruby code above; the code's almost as simple to read.)
But notice the changes in the last 3 verses:
2 bottles of beer on the wall, 2 bottles of beer.
Take one down and pass it around, 1 bottle of beer on the wall.
1 bottle of beer on the wall, 1 bottle of beer.
Take it down and pass it around, no more bottles of beer on the wall.
No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.
And that's why it's a programming challenge. If it was just about writing those 5 lines of code above, it wouldn't be too tricky.
But what's interesting is when you have exceptions to the rules, and those last 3 verses are just that. They don't even follow a single, different set of rules - they're each different in their own way.
How you go about handling that is up to you, though. It's a challenge, after all. There are clever ways, simple ways, complex ways, nonsensical ways... which one you pick is up to you. The idea is to make you consider the problem and its potential solutions; there isn't a single correct answer. The destination is already given (print the lyrics), so it's all about the journey.
Other small stuff:
In your case,
var1 is completely non-descriptive. A better name would be bottles, bottle_count or bottles_remaining to be even more specific.Secondly, in Ruby, you rarely need to use a plain
loop. In your case, you basically want to repeat roughly the same thing 99 times (well actually, no, you don't exactly, but we'll get to that later).A simple way to do this in Ruby is to say:
99.downto(1) do |remaining|
# stuff to do 99 times
endThe
remaining variable will start at 99 and count down to 1, so we can use it to print the verses.And speaking of printing, you're making things difficult for yourself by not using string interpolation.
If you use double quotes instead of single quotes, you can use
#{...} to insert stuff into strings. Like so:99.downto(1) do |remaining|
puts "#{remaining} bottles of beer on the wall, #{remaining} bottles of beer."
puts "Take one down and pass it around, #{remaining-1} bottles of beer on the wall."
puts # print a blank line between verses.
endNote that
#{...} can contain any Ruby code (but keep it simple for your own sake!), so a bit of arithmetic to subtract 1 works too. And there's no need to use to_s everywhere, as that happens automatically when using string interpolation.The above code is pretty much equivalent to your current code, except that it prints a blank line between verses. And the fact that it prints 99 verses - you're actually only printing 98 verses in your version.
... However, it's printing wrong lyrics. Grammatically incorrect lyrics, at any rate.
Most verses do indeed go like this:
X bottles of beer on the wall, X bottles of beer.
Take one down and pass it around, (X-1) bottles of beer on the wall.
where X is whatever number of bottles we have left. (Note, by the way, how much this looks like the Ruby code above; the code's almost as simple to read.)
But notice the changes in the last 3 verses:
2 bottles of beer on the wall, 2 bottles of beer.
Take one down and pass it around, 1 bottle of beer on the wall.
1 bottle of beer on the wall, 1 bottle of beer.
Take it down and pass it around, no more bottles of beer on the wall.
No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.
And that's why it's a programming challenge. If it was just about writing those 5 lines of code above, it wouldn't be too tricky.
But what's interesting is when you have exceptions to the rules, and those last 3 verses are just that. They don't even follow a single, different set of rules - they're each different in their own way.
How you go about handling that is up to you, though. It's a challenge, after all. There are clever ways, simple ways, complex ways, nonsensical ways... which one you pick is up to you. The idea is to make you consider the problem and its potential solutions; there isn't a single correct answer. The destination is already given (print the lyrics), so it's all about the journey.
Other small stuff:
- The Ruby convention is to use 2 spaces of indentation - not 4 spaces, not tabs.
- The
breakline should be indented.
- The parentheses in
var1 = (var1 - 1)are completely unnecessary. Furthermore, you can write it asvar1 -= 1, which is a shorthand for the same thing.
Code Snippets
99.downto(1) do |remaining|
# stuff to do 99 times
end99.downto(1) do |remaining|
puts "#{remaining} bottles of beer on the wall, #{remaining} bottles of beer."
puts "Take one down and pass it around, #{remaining-1} bottles of beer on the wall."
puts # print a blank line between verses.
endContext
StackExchange Code Review Q#79220, answer score: 29
Revisions (0)
No revisions yet.