[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Okay, trying this again from the beginning

JB

4/14/2006 12:07:00 AM


Hi gang,

I got pretty frustrated with trying to learn to program, that I just gave it
up for a while. Then, I finally got the revised edition book of 'Learn to
Program' by Chris Pine, instead of trying to work off the website with the
old version of it.
So, now I'm back at the '99 bottles of beer' thing, and this is what I came
up with:

beer = 100
while beer >= 2
beer = (beer - 1)
puts beer.to_s + ' bottles of beer on the wall, ' + beer.to_s + ' bottles of
beeer,'
puts 'take one down, pass it around, ' + (beer - 1).to_s + ' bottles of beer
on the wall!'
if beer == 1
puts beer.to_s + ' bottle of beer on the wall, ' + beer.to_s + ' bottle
of beeer,'
puts 'take one down, pass it around, ' + (beer - 1).to_s + ' bottles of
beer on the wall!'
elsif beer != 1 && (beer - 1) == 1
puts beer.to_s + ' bottles of beer on the wall, ' + beer.to_s + '
bottles of beeer,'
puts 'take one down, pass it around, ' + (beer - 1).to_s + ' bottle of
beer on the wall!'
end
end

It's messy in this newsreader, but in an IDE, it looks fine.
The problem I'm having is, it seems 'bloated' and, at the end, it prints
this:

2 bottles of beer on the wall, 2 bottles of beeer,
take one down, pass it around, 1 bottles of beer on the wall!
2 bottles of beer on the wall, 2 bottles of beeer,
take one down, pass it around, 1 bottle of beer on the wall!
1 bottles of beer on the wall, 1 bottles of beeer,
take one down, pass it around, 0 bottles of beer on the wall!
1 bottle of beer on the wall, 1 bottle of beeer,
take one down, pass it around, 0 bottles of beer on the wall!

Why does it do the '2 bottles' once correctly and once incorrectly, and also
the '1 bottles' it does it the same way?

Thanks again for putting up with this new learner to programming.

JB
30 Answers

anne001

4/14/2006 1:11:00 AM

0

if it does it, you must be telling it to do so!!!
well, beer=3
so beer =3-1 =2
so it prints it a first time, your first put

then elsif beer != 1 && (beer - 1) == 1
when beer=2, beer!=1 and beer-1==1
so off you go again printing beerto_s
(puts in the elsif section).

then beer =2-1=1
the first put is going to write it once,
the put in the section beer==1 is going to put it a second time...

You are a brave sole to start at 100!

Dave Burt

4/14/2006 4:11:00 AM

0

JB wrote:
> Hi gang,
>
> I got pretty frustrated with trying to learn to program, that I just gave it
> up for a while. Then, I finally got the revised edition book of 'Learn to
> Program' by Chris Pine, instead of trying to work off the website with the
> old version of it.
> So, now I'm back at the '99 bottles of beer' thing, and this is what I came
> up with:
>
> beer = 100

Try starting with a smaller number :)

> while beer >= 2
> beer = (beer - 1)

Try moving beer= to the end of the loop.

> puts beer.to_s + ' bottles of beer on the wall, ' + beer.to_s + ' bottles of
> beeer,'
> puts 'take one down, pass it around, ' + (beer - 1).to_s + ' bottles of beer
> on the wall!'

This stuff will be done every time - it's not in an "if". You probably
want to only do this if beer isn't 1 or 2 - so move it into an "else"
under the if block below.

> if beer == 1

The following stuff will be done (extra) if beer == 1

> puts beer.to_s + ' bottle of beer on the wall, ' + beer.to_s + ' bottle
> of beeer,'
> puts 'take one down, pass it around, ' + (beer - 1).to_s + ' bottles of
> beer on the wall!'
> elsif beer != 1 && (beer - 1) == 1

This can be rewritten as "elsif beer == 1"

> puts beer.to_s + ' bottles of beer on the wall, ' + beer.to_s + '
> bottles of beeer,'
> puts 'take one down, pass it around, ' + (beer - 1).to_s + ' bottle of
> beer on the wall!'
> end
> end

Good work.

> It's messy in this newsreader, but in an IDE, it looks fine.

You can break the long lines like this. If you end a line with a + or
leave a ( without a ), it continues on the next line:

puts beer.to_s + ' bottles of beer on the wall, ' +
beer.to_s + ' bottles of beeer,'

> The problem I'm having is, it seems 'bloated' and, at the end, it prints
> this:

The multi-printing is caused by the problem I noted above.

About being "bloated" - it might help to two bottles variables to store
"bottle" or "bottles" depending on the amount of beer left.

Cheers,
Dave

Timothy Goddard

4/14/2006 7:17:00 AM

0

I have two suggestions here. The first is to use the downto method
instead of a normal loop:

100.downto(2) do |bottles|
... # In here the variable bottles represents the number remaining
end

This will handle all the looping behind the scenes.

My second piece of advice is to use Ruby's ability to substitute values
into strings using #{code_goes_here}. The value of whatever is inside
the curly braces will automatically have to_s called on it then will be
inserted into the text. The end result would be:

100.downto(2) do |bottles|
puts "#{bottles} bottles of beer on the wall, #{bottles} bottles of
beer."
puts "Take one down, pass it around, #{bottles - 1} bottles of beer
on the wall!"
end

If you can read and understand all of that, you're well on your way to
learning to program. Keep it up.

JB

4/14/2006 3:40:00 PM

0

Timothy Goddard wrote:

> I have two suggestions here. The first is to use the downto method
> instead of a normal loop:
>
> 100.downto(2) do |bottles|
> ... # In here the variable bottles represents the number remaining
> end
>
> This will handle all the looping behind the scenes.
>
> My second piece of advice is to use Ruby's ability to substitute values
> into strings using #{code_goes_here}. The value of whatever is inside
> the curly braces will automatically have to_s called on it then will be
> inserted into the text. The end result would be:
>
> 100.downto(2) do |bottles|
> puts "#{bottles} bottles of beer on the wall, #{bottles} bottles of
> beer."
> puts "Take one down, pass it around, #{bottles - 1} bottles of beer
> on the wall!"
> end
>
> If you can read and understand all of that, you're well on your way to
> learning to program. Keep it up.
>

Thanks for all that. It'll come in handy when I get further in the book, but
for now I'm still trying to learn the basics, heh.
The main problem I'm having is getting the thing to say 'bottle' instead of
'bottles' if it is only '1'.
I tried this, after a few other suggestions, but it's almost like it ignores
the 'elsif' thing:

beer = 10
while beer >= 2
beer = (beer - 1)
if beer != 1
puts beer.to_s + ' bottles of beer on the wall, ' + beer.to_s + '
bottles of beeer,'
puts 'take one down, pass it around, ' + (beer - 1).to_s + ' bottle of
beer on the wall!'
elsif beer == 1
puts beer.to_s + ' bottle of beer on the wall, ' + beer.to_s + ' bottle
of beeer,'
puts 'take one down, pass it around, ' + (beer - 1).to_s + ' bottles of
beer on the wall!'
end
end

I've tried everything (that I've learned so far in the book up to the end of
this chapter), and it's really throwing me for a loop...no pun intended, heh.

JB

Daniel Schierbeck

4/14/2006 5:11:00 PM

0

JB wrote:
> Timothy Goddard wrote:
>
>> I have two suggestions here. The first is to use the downto method
>> instead of a normal loop:
>>
>> 100.downto(2) do |bottles|
>> ... # In here the variable bottles represents the number remaining
>> end
>>
>> This will handle all the looping behind the scenes.
>>
>> My second piece of advice is to use Ruby's ability to substitute values
>> into strings using #{code_goes_here}. The value of whatever is inside
>> the curly braces will automatically have to_s called on it then will be
>> inserted into the text. The end result would be:
>>
>> 100.downto(2) do |bottles|
>> puts "#{bottles} bottles of beer on the wall, #{bottles} bottles of
>> beer."
>> puts "Take one down, pass it around, #{bottles - 1} bottles of beer
>> on the wall!"
>> end
>>
>> If you can read and understand all of that, you're well on your way to
>> learning to program. Keep it up.
>>
>
> Thanks for all that. It'll come in handy when I get further in the book, but
> for now I'm still trying to learn the basics, heh.
> The main problem I'm having is getting the thing to say 'bottle' instead of
> 'bottles' if it is only '1'.
> I tried this, after a few other suggestions, but it's almost like it ignores
> the 'elsif' thing:
>
> beer = 10
> while beer >= 2
> beer = (beer - 1)
> if beer != 1
> puts beer.to_s + ' bottles of beer on the wall, ' + beer.to_s + '
> bottles of beeer,'
> puts 'take one down, pass it around, ' + (beer - 1).to_s + ' bottle of
> beer on the wall!'
> elsif beer == 1
> puts beer.to_s + ' bottle of beer on the wall, ' + beer.to_s + ' bottle
> of beeer,'
> puts 'take one down, pass it around, ' + (beer - 1).to_s + ' bottles of
> beer on the wall!'
> end
> end
>
> I've tried everything (that I've learned so far in the book up to the end of
> this chapter), and it's really throwing me for a loop...no pun intended, heh.
>
> JB

try this:

beer = 100
beer.downto(3) do |bottles|
print "#{bottles} bottles of beer on the wall, "
print "#{bottles} bottles of beer\n"
print "take one down, pass it around, "
print "#{bottles - 1} bottles of beer on the wall!\n"
end
print "2 bottles of beer on the wall, 2 bottles of beer\n"
print "take one down, pass it around, 1 bottle of beer on the wall!\n"
print "1 bottle of beer on the wall, 1 bottle of beer\n"
print "take one down, pass it around, no bottles of beer on the wall :("


Cheers,
Daniel

Daniel Schierbeck

4/14/2006 6:06:00 PM

0

Had a bit of fun with it:

class Wall
def initialize(bottles = 20)
@bottles = bottles
end

def bottles
"#{@bottles > 0 ? @bottles : 'no'}" +
"bottle#{'s' if @bottles != 1} of beer"
end

def take_one_down
@bottles -= 1
"take one down"
end

def commence_drinking
while @bottles > 0
puts "#{bottles} on the wall, #{bottles}"
puts "#{take_one_down}, pass it around, #{bottles} on the wall!"
end
end
end

Wall.new(20).commence_drinking

anne001

4/14/2006 7:03:00 PM

0

works for me, bottles, and then bottle.

3 bottles of beer on the wall, 3 bottles of beeer,
take one down, pass it around, 2 bottle of
beer on the wall!

2 bottles of beer on the wall, 2 bottles of beeer,
take one down, pass it around, 1 bottle of beer on the wall!

1 bottle of beer on the wall, 1 bottle of beeer,
take one down, pass it around, 0 bottles of beer on the wall!

Don't worry about learning to program. Think of this as a language,
like japonese (which it is). Look at the suggestions, try them, see
what they do. Have fun with it.

JB

4/15/2006 4:18:00 PM

0

anne001 wrote:

> works for me, bottles, and then bottle.
>
> 3 bottles of beer on the wall, 3 bottles of beeer,
> take one down, pass it around, 2 bottle of
> beer on the wall!

It works except that at '2', it puts 'bottle' instead of 'bottles'.

> Don't worry about learning to program. Think of this as a language,
> like japonese (which it is). Look at the suggestions, try them, see
> what they do. Have fun with it.
>

I have to learn to do things correctly, or else I'll be making similar
mistakes in *every* program I try to make. That's why I'm not going any
farther forward until I can figure out (with what I've only learned in the
book) so far. Learning a language is the very same way. I know...I speak,
read and write 3 different ones. ;)

It's not that I'm not using the suggestions, I'm trying to utilize them with
the knowledge *I* have at the moment. I can't take someone's suggestion and
just 'use' it...I wouldn't be learning anything, like the how and why...it
worked.

JB

David Sletten

4/15/2006 10:10:00 PM

0

JB wrote:

> Hi gang,
>
> I got pretty frustrated with trying to learn to program, that I just gave it
> up for a while. Then, I finally got the revised edition book of 'Learn to
> Program' by Chris Pine, instead of trying to work off the website with the
> old version of it.
> So, now I'm back at the '99 bottles of beer' thing, and this is what I came
> up with:
>
> beer = 100
> while beer >= 2
> beer = (beer - 1)
> puts beer.to_s + ' bottles of beer on the wall, ' + beer.to_s + ' bottles of
> beeer,'
> puts 'take one down, pass it around, ' + (beer - 1).to_s + ' bottles of beer
> on the wall!'
> if beer == 1
> puts beer.to_s + ' bottle of beer on the wall, ' + beer.to_s + ' bottle
> of beeer,'
> puts 'take one down, pass it around, ' + (beer - 1).to_s + ' bottles of
> beer on the wall!'
> elsif beer != 1 && (beer - 1) == 1
> puts beer.to_s + ' bottles of beer on the wall, ' + beer.to_s + '
> bottles of beeer,'
> puts 'take one down, pass it around, ' + (beer - 1).to_s + ' bottle of
> beer on the wall!'
> end
> end
>
> It's messy in this newsreader, but in an IDE, it looks fine.
> The problem I'm having is, it seems 'bloated' and, at the end, it prints
> this:
>
> 2 bottles of beer on the wall, 2 bottles of beeer,
> take one down, pass it around, 1 bottles of beer on the wall!
> 2 bottles of beer on the wall, 2 bottles of beeer,
> take one down, pass it around, 1 bottle of beer on the wall!
> 1 bottles of beer on the wall, 1 bottles of beeer,
> take one down, pass it around, 0 bottles of beer on the wall!
> 1 bottle of beer on the wall, 1 bottle of beeer,
> take one down, pass it around, 0 bottles of beer on the wall!
>
> Why does it do the '2 bottles' once correctly and once incorrectly, and also
> the '1 bottles' it does it the same way?
>
> Thanks again for putting up with this new learner to programming.
>
> JB

One very important idea in successful programming is the use of
abstraction. We see a number of similar, though not identical,
operations and recognize that there is an underlying sameness if we
ignore the specific details.

Let's say we find ourselves checking repeatedly whether certain numbers
are even. We can do this by checking the remainder after dividing by 2.
If a number is odd we end up with 1. If it's even we get 0. So our
program looks like this:
if x % 2 == 0 then ...
if y % 2 == 0 then ...
if a % 2 != 0 then ...

The salient aspect of all of these tests is to check the "eveness" of a
number. So we use abstraction to define this test in a general case.
Given any number x, x % 2 == 0 means x is even:
def even?(x)
if x % 2 == 0 then true
else false
end
end

Of course, this can be simplified:
def even?(x)
return x % 2 == 0 # return can be implicit here
end

And simplified to the extreme:
def even?(x)
(x % 2).zero?
end

Now our intent in the rest of our program is clearer:
if even?(x) then ...
if even?(y) then ...
if !even?(a) then ...

In your case, you have a situation where you need to repeatedly
determine the correct pluralization of the word "bottle" based on a
bottle count. It will greatly simplify your program if you separate out
this oft used pattern:
def pluralize(string, count)
if count == 1 then string
else string + "s"
end
end

Now we get:
pluralize("bottle", 2) => "bottles"
pluralize("bottle", 1) => "bottle"
pluralize("bottle", 0) => "bottles"

This simple function will not handle all of the complexity of English
spelling, but we can extend it easily:
def pluralize(base, count, suffix="s", suffix1="")
if count == 1 then base + suffix1
else base + suffix
end
end

Now we get:
pluralize("bottle", 0) => "bottles" # Easy case is still easy
pluralize("bottle", 1) => "bottle"
pluralize("pupp", 1, "ies", "y") => "puppy"
pluralize("pupp", 2, "ies", "y") => "puppies"
pluralize("child", 1, "ren") => "child"
pluralize("child", 2, "ren") => "children"
pluralize("ind", 1, "ices", "ex") => "index" # Complex cases now possible
pluralize("ind", 2, "ices", "ex") => "indices"
pluralize("medi", 1, "a", "um") => "medium"
pluralize("medi", 2, "a", "um") => "media"

This function probably uses some Ruby features which you haven't studied
yet. It's also probably not complete for all possible plurals, but it
gets us pretty far.

Now we can streamline your program:
100.downto(1) do |i|
puts("#{i} #{pluralize("bottle", i)} of beer on the wall.")
puts("#{i} #{pluralize("bottle", i)} of beer...")
puts("You take one down and pass it around--")
puts("#{i-1} #{pluralize("bottle", i-1)} of beer on the wall.")
puts
end

Here we take advantage of an abstraction built into Ruby--the common
pattern of counting down successive integers from a starting number to
an ending number. Then we utilize our own abstraction to handle the
logic of pluralizing. I hope this helps you see the effectiveness of
using abstractions to your advantage. Look for common patterns that can
be generalized when you work on your programs.

Aloha,
David Sletten

anne001

4/16/2006 10:41:00 AM

0

As you say, people learn differently. My first program, I tried
different ways people
suggested, but this is not my first prog language.

As well as programming, debugging skills are important. So what bothers
you is the take one down line.
the line ont the wall and take one down are part of the same "block"
but they are independent. so
copy and paste your program, and delete the lines that work

beer = 10
while beer >= 2
beer = (beer - 1)
if beer != 1
pass it around, ' + (beer - 1).to_s + ' bottle of beer on the
wall!'
elsif beer == 1
pass it around, ' + (beer - 1).to_s + ' bottles of beer on the
wall!'
end
end
now you see that for beer different from one, you did not put an s at
bottle of beer on
the wall. Is that what you wanted?