14 Replies - 2742 Views - Last Post: 07 October 2011 - 03:58 PM Rate Topic: -----

#1 Redalin  Icon User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 23
  • Joined: 02-October 11

Newbie: Nesting loops and getting results - wrong method?

Posted 02 October 2011 - 03:52 PM

Hi,

I'm new to Ruby, and am having issues getting it to do what I need. It is an easier language than C++ (when I tried to learn it), and I am slowly (but surely) catching onto it.

I am trying to get the average amount of rainfall for all months, the amount of months and average rainfall per month. I think I am using the wrong thing (attr_accesor) to get what I need, I might have the right idea but I'm not doing it the correct way.



The first loop I made collects the amount of years and iterates once. The nested loop asks the user for the amount of inches of rain per month and iterates 12 times. At least, I think that's what I'm telling it to do.


class Screen
  def cls
    puts ("\n" * 25)
  end
end

class Amount
    attr_accessor :year
    attr_accessor :Jan, :Feb, :Mar, :Apr, :May, :Jun, :Jul, :Aug, :Sep, :Oct, :Nov, :Dec
end


Inches = Amount.new


  puts "How many years to calculate?"
  year = STDIN.gets
  year.chop!
  
  loop do
    if year.to_i < 1
      puts "Do not insert a number less than 1 year."  
    answer = STDIN.gets     
    break if year.to_i >= 1
    end
    
      #MONTHS
     puts "Rainfall for January? "
     Jan = STDIN.gets


The rest of the months follow using same syntax. The code continues with:

    
    #Invalid number, negative number for monthly rainfall
    if Inches.to_i <= 0
    puts "Cannot insert a negative number for amount of rainfall"
    break if Inches.to_i >= 1
    
    end
end




I do get errors but they're something silly with the loop and math operators and I'm trying to work them out right now. I am pretty sure I am able to calculate the average and months at the end on my own, so I did not include it in the code.

Can anyone point out what part of the code I need to look into or suggest a better way?

Is This A Good Question/Topic? 0
  • +

Replies To: Newbie: Nesting loops and getting results - wrong method?

#2 Skaggles  Icon User is offline

  • THE PEN IS MIGHTIER
  • member icon





Reputation: 251
  • View blog
  • Posts: 640
  • Joined: 01-March 09

Re: Newbie: Nesting loops and getting results - wrong method?

Posted 02 October 2011 - 04:08 PM

I noticed you using chop! in your code, which removes the last character of a string. Perhaps, what you meant to use was chomp!.

chop will remove the last character of a string, so "1" will become "". On the other hand, chomp will remove what you tell it to, or new line characters by default; "1\r\n" will become "1" but "1" will stay "1". There's also strip, which will remove any leading or trailing white space.

This post has been edited by Skaggles: 02 October 2011 - 04:20 PM
Reason for edit:: provided more details

Was This Post Helpful? 2
  • +
  • -

#3 Redalin  Icon User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 23
  • Joined: 02-October 11

Re: Newbie: Nesting loops and getting results - wrong method?

Posted 02 October 2011 - 04:37 PM

Thanks, Skaggles! My group partner and I were wondering what the difference was the other day!
Was This Post Helpful? 0
  • +
  • -

#4 Redalin  Icon User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 23
  • Joined: 02-October 11

Re: Newbie: Nesting loops and getting results - wrong method?

Posted 02 October 2011 - 08:42 PM

I'm getting closer to getting it, I think, but I am having issues getting past the Year part. The book lists using
year <= 0
as a way of stating that you cannot enter a number below 1 for the year, but I am getting errors pointing to the math operator ( <= ).

Am I using the math operator incorrectly? The book I am using does not specify having to load anything.

The new code is below, I removed the attr_accessor since I noticed I didn't really need it after experimenting with it in IRB with a lesson I did prior to this.



class Screen
  def cls
    puts ("\n" * 25)
  end
end

class Measure
  def inc
     puts "inches "
  end
end


Inches = Measure.new
Console_Screen = Screen.new
Console_Screen.cls

  puts "How many years?"
  year = STDIN.gets
  year.chomp!
  
      while (year <= 0) do
      puts "Do not insert a number less than 1 year."  
      break if year >= 1


    loop do
    #MONTHS
    #Invalid number entered for monthly rainfall
    if (reply < 1)
    puts "Cannot insert a negative number for amount of rainfall"
    break if reply>= 1

     puts "Rainfall for January? "
     Jan = STDIN.gets
     Jan.chomp!

 # D.I.C. - Other months removed, but follow same syntax as above month of January
     

    
 # Collect and display information
 #  puts "The average rainfall of all years was " inches.to_i / year.to_i ".\n"
 #  puts "The average rainfall per month was " inches.to_i / year.to_i ".\n"
 #  puts "The number of months was " year.to_i * 12 ".\n"
   end
  end
 end
end


Was This Post Helpful? 0
  • +
  • -

#5 Skaggles  Icon User is offline

  • THE PEN IS MIGHTIER
  • member icon





Reputation: 251
  • View blog
  • Posts: 640
  • Joined: 01-March 09

Re: Newbie: Nesting loops and getting results - wrong method?

Posted 02 October 2011 - 10:50 PM

I believe the problem could be that year = STDIN.gets returns a string, but with while (year <= 0) do you are comparing a string with an integer. Try using year.to_i to convert it to an integer and see if that helps.
Was This Post Helpful? 2
  • +
  • -

#6 Redalin  Icon User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 23
  • Joined: 02-October 11

Re: Newbie: Nesting loops and getting results - wrong method?

Posted 03 October 2011 - 11:59 AM

Interesting, I never knew the STDIN.gets returns a string, I thought it only records the user input.

It will not run the script without having the STDIN.gets. I also tried STDIN.read, but get the same error (math operator comparing an integer to a string).

  puts "How many years?"
  years = years.to_i
  years = STDIN.gets
  years.chomp!


Returns "Path: in `<=': comparison of String with 0 failed (ArgumentError)"


I also tried converting it to an integer right after "puts" but I still get an error.
  puts "How many years?".to_i
        years.chomp!


Returns "Path: in `<main>': undefined local variable or method `years' for main:Object (NameError)

Is there a way for Ruby to accept an integer, not a string like STDIN.gets does?

This post has been edited by Redalin: 03 October 2011 - 11:59 AM

Was This Post Helpful? 0
  • +
  • -

#7 xclite  Icon User is offline

  • LIKE A BOSS
  • member icon


Reputation: 911
  • View blog
  • Posts: 3,178
  • Joined: 12-May 09

Re: Newbie: Nesting loops and getting results - wrong method?

Posted 03 October 2011 - 12:08 PM

View PostRedalin, on 03 October 2011 - 02:59 PM, said:

Interesting, I never knew the STDIN.gets returns a string, I thought it only records the user input.

Where would it record the input if not by returning it?

Quote

It will not run the script without having the STDIN.gets. I also tried STDIN.read, but get the same error (math operator comparing an integer to a string).

You shouldn't need STDIN - gets is as available as puts.

Quote

I also tried converting it to an integer right after "puts" but I still get an error.
  puts "How many years?".to_i
        years.chomp!


Returns "Path: in `<main>': undefined local variable or method `years' for main:Object (NameError)

There seems to be a lack of understanding here. General methodology for getting a value from the command line:
  puts "Enter years:
  years = gets.to_i
  i = 0
  while i < years do
...


Your error was because you never had a variable or anything called years. Your code puts "How many years?".to_i tried to convert the string "How many years" to an int and then output it, which doesn't really make sense, does it? When you wrote that line - what was the thought process like? When making the changes - think about who you're acting on. Nothing in that line was related to the input variable, yet you expected it to make years hold the value you wanted.
Was This Post Helpful? 2
  • +
  • -

#8 Redalin  Icon User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 23
  • Joined: 02-October 11

Re: Newbie: Nesting loops and getting results - wrong method?

Posted 03 October 2011 - 01:23 PM

View Postxclite, on 03 October 2011 - 02:08 PM, said:

Your error was because you never had a variable or anything called years. Your code puts "How many years?".to_i tried to convert the string "How many years" to an int and then output it, which doesn't really make sense, does it? When you wrote that line - what was the thought process like? When making the changes - think about who you're acting on. Nothing in that line was related to the input variable, yet you expected it to make years hold the value you wanted.


I was seeing if it was possible for puts to convert it to an integer so that STDIN.gets would accept it as-is instead of it being a string. Apparently it doesn't, it gave me an error >.<


This is what I have right now, and it seems to be working so far. I believe I need to make the Years variable and replace it where answer is? I didn't know .gets was as available as you said, thanks!

  puts "How many years?"
  answer = gets
  answer.chomp!
  
    while (answer.to_i <= 0) do
    puts "Do not insert a number less than 1 year. How many years?"
    answer = gets
    break if (answer.to_i >= 1)
    end


The next step is to make the outer loop iterate once and the inner loop (months) iterate as many times as the year(s) inputted. This might take awhile :bigsmile:
Was This Post Helpful? 0
  • +
  • -

#9 Redalin  Icon User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 23
  • Joined: 02-October 11

Re: Newbie: Nesting loops and getting results - wrong method?

Posted 05 October 2011 - 10:46 PM

Okay,

I have everything narrowed down and fixed. But, I am needing to make the script not accept an input of 0 for years. What I have is below.

  loop do
    print "How many years are you wanting to know the statistics for? "
    years = gets
    years.chomp!
    years.to_f 
      break if years.to_f > 0
  end


Is there a reason why it is not looping back to print when the input is below 1 and not continuing with the script when it meets the condition?
Was This Post Helpful? 0
  • +
  • -

#10 Skaggles  Icon User is offline

  • THE PEN IS MIGHTIER
  • member icon





Reputation: 251
  • View blog
  • Posts: 640
  • Joined: 01-March 09

Re: Newbie: Nesting loops and getting results - wrong method?

Posted 05 October 2011 - 11:45 PM

View PostRedalin, on 05 October 2011 - 10:46 PM, said:

Okay,

I have everything narrowed down and fixed. But, I am needing to make the script not accept an input of 0 for years. What I have is below.

  loop do
    print "How many years are you wanting to know the statistics for? "
    years = gets
    years.chomp!
    years.to_f 
      break if years.to_f > 0
  end


Is there a reason why it is not looping back to print when the input is below 1 and not continuing with the script when it meets the condition?


Can you be more specific about what's not working? I used your exact code and it worked fine on my end. Any number below 1 looped back to print, and any number greater than 0 would exit the loop.
Was This Post Helpful? 0
  • +
  • -

#11 Redalin  Icon User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 23
  • Joined: 02-October 11

Re: Newbie: Nesting loops and getting results - wrong method?

Posted 06 October 2011 - 01:15 AM

Of course :helpsmilie:

It just points back to print even if the number meets the condition to exit the loop. I'm not sure if it's how my code is set up, but here's an overview of it (end of loop at end of script file):


loop do
  Console_Screen.cls
  print "How many years are you wanting to know the statistics for? "
  years = STDIN.gets
  years = years.chomp!
  years = years.to_i
  Console_Screen.cls
  if years.to_i < 1
    puts "You must insert a 1 or higher for amount of years!\n"


  break if years.to_i > 0
  end 


(1..years).each do |years| #Outer loop
    (1..12).each do |month| #Inner Loop
      
#Loops all-in-one sentence
        print "Input rainfall inches for year #{years}, month #{month}: "
        total_inches += gets.chomp.to_f #Sweet shortcut from D.I.C. forums
        
         if total_inches < 0
            puts "Number cannot be negative, try again."
            break if total_inches >= 0 
         end
    end #Inner loop


With this code, it does exit the loop but it shows the statistics screen after each year (even if you choose 5 years, it'll show it after each year but will add all the numbers correctly).

This post has been edited by Redalin: 06 October 2011 - 01:16 AM

Was This Post Helpful? 0
  • +
  • -

#12 NotarySojac  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 53
  • View blog
  • Posts: 428
  • Joined: 30-September 10

Re: Newbie: Nesting loops and getting results - wrong method?

Posted 06 October 2011 - 03:50 PM

View PostRedalin, on 06 October 2011 - 01:15 AM, said:

Of course :helpsmilie:

It just points back to print even if the number meets the condition to exit the loop. I'm not sure if it's how my code is set up, but here's an overview of it (end of loop at end of script file):

...


With this code, it does exit the loop but it shows the statistics screen after each year (even if you choose 5 years, it'll show it after each year but will add all the numbers correctly).


It's still not entirely clear what the issues are, but it looks like maybe you're expecting the loops to work differently than they actually do. Do you have the debugger setup? Watching the code tick might help clear things up. Debugging is pretty hit and miss in ruby right now, I think debuggers will only work with ruby >= 1.8.7.


Here's a sample of a project I'm working on atm to develop my ruby skills (file manipulation is 1000 times better for learning a language than logic problems IMO, btw).


      puts "This is a yes or no question.  Will you answer it?"
      puts "[y/n]"
      
      while true
        answer = STDIN.gets.strip
        case answer
          when "y"
            puts "you said yes"
            break  # exits the while loop
          when "n"
            puts "You said no"
            break  # exits the while loop
          else
            puts "plz answer 'y' or 'n'"
            # does not exit the while loop
        end
      end




I think there's a bug in your code where you break if total_inches >= 0 you might want that break to be a 'redo' possibly? Also with a debugger, watch the value of total_inches to see that it is what you expect it to be.



Thanks btw for posting those eclipse ide instructions, I'm trying out eclipse now and it's going pretty good. I'm having trouble with unit testing on a gem though =(

This post has been edited by NotarySojac: 06 October 2011 - 03:52 PM

Was This Post Helpful? 0
  • +
  • -

#13 Redalin  Icon User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 23
  • Joined: 02-October 11

Re: Newbie: Nesting loops and getting results - wrong method?

Posted 06 October 2011 - 07:28 PM

View PostNotarySojac, on 06 October 2011 - 05:50 PM, said:

It's still not entirely clear what the issues are, but it looks like maybe you're expecting the loops to work differently than they actually do. Do you have the debugger setup? Watching the code tick might help clear things up. Debugging is pretty hit and miss in ruby right now, I think debuggers will only work with ruby >= 1.8.7.


Here's a sample of a project I'm working on atm to develop my ruby skills (file manipulation is 1000 times better for learning a language than logic problems IMO, btw).


      puts "This is a yes or no question.  Will you answer it?"
      puts "[y/n]"
      
      while true
        answer = STDIN.gets.strip
        case answer
          when "y"
            puts "you said yes"
            break  # exits the while loop
          when "n"
            puts "You said no"
            break  # exits the while loop
          else
            puts "plz answer 'y' or 'n'"
            # does not exit the while loop
        end
      end




I think there's a bug in your code where you break if total_inches >= 0 you might want that break to be a 'redo' possibly? Also with a debugger, watch the value of total_inches to see that it is what you expect it to be.



Thanks btw for posting those eclipse ide instructions, I'm trying out eclipse now and it's going pretty good. I'm having trouble with unit testing on a gem though =(


It is executing correctly, but I am trying to make the statistics screen appear after the amount of years the user inputs. Right now, it comes up after every year regardless if you said one or 5 years. The statistics screen is just calling in the integer values from the loops, it's really nothing special. I'll see if redo will work, do I put it as redo if < 1 years?

No problem with letting you know about Eclipse, I like it a lot. What does the debugging part do, run the code line by line (I really don't know, the professor said not to worry about it)? Also, where can I do some of this file manipulation that you speak of?
Was This Post Helpful? 0
  • +
  • -

#14 NotarySojac  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 53
  • View blog
  • Posts: 428
  • Joined: 30-September 10

Re: Newbie: Nesting loops and getting results - wrong method?

Posted 06 October 2011 - 09:28 PM

View PostRedalin, on 06 October 2011 - 07:28 PM, said:

It is executing correctly, but I am trying to make the statistics screen appear after the amount of years the user inputs. Right now, it comes up after every year regardless if you said one or 5 years.


by statistics, do you mean the output of this line of code?
print "Input rainfall inches for year #{years}, month #{month}: "



If so, strongly I recommend that you single step through your code using a debugger and watch what happens. Unless I'm misunderstanding what you mean, it should become pretty obvious after a few observations what you need to do in order to get your desired result. Do you know how to set break points? I can't remember my entry level C++ class going over debuggers at all, which is pretty ridiculous.

View PostRedalin, on 06 October 2011 - 07:28 PM, said:

No problem with letting you know about Eclipse, I like it a lot. What does the debugging part do, run the code line by line (I really don't know, the professor said not to worry about it)?


OMG, your professor is a capital goon! Debuggers allow you to step through your code line by line. So if you're unfamiliar with how code executes, you can simply place a "breakpoint" on the first instruction you'd like to begin observing, and then click "DEBUG" and your code will execute line by line as you hit the 'F6' key in eclipse.

Setting up your environment for debugging:
1) Make sure you have ruby 1.8.7 installed somewhere (hopefully you've got rvm setup)
$ ruby -v should spew out something about 1.8.7

2) Install the ruby-debug gem under your 1.8.7 ruby environment
$  gem install ruby-debug


Debugging in eclipse:
1) Create a test project, just call it hello or something.


2) Add hello.rb to that project
Right click the project in the project explorer and select
New -> Empty Ruby Script

3) Fill in some code to debug
years = 2
total_inches = 0

(1..years).each do |years| #Outer loop
    (1..12).each do |month| #Inner Loop
      
        #Loops all-in-one sentence
        print "Input rainfall inches for year #{years}, month #{month}: "
        total_inches += gets.chomp.to_f #Sweet shortcut from D.I.C. forums
        
        if total_inches < 0
           puts "Number cannot be negative, try again."
           break if total_inches >= 0 
        end
    end #Inner loop
end




4) Add a breakpoint to that code on the first line
Double click to the left of the first line. This should make a bullet point appear. This point signifies that execution will halt when the interpreter gets to that instruction.


5) Configure the debug settings for your ruby file.
Right click hello.rb and select...
Debug as -> [Debug Configurations]

Ruby Script(left pane) -> New Launch Configuration(icon)

Interpreter(tab) -> [Choose ruby 1.8.7]

You may need to click "Installed interpreters..." and click "Add" and specify the path to ruby 1.8.7.

You can find the path to ruby on linux by running
$ which ruby

On windows it's usually lingering around on your C:/ drive
C:\Ruby187\bin\ruby.exe


After that's done with, click "Debug".


From now on, you can start a debug session simply by clicking the little icon with the bug on it and choosing "New Configuration" or what ever you named the configuration we just setup.

6) Switch to the Debug perspective (upper right corner, or click "yes")

The debug perspective has a play button, a pause button, and a step button. (by default, these are located within the debug window, upper left)

When the play button is pressed, execution proceeds to the next breakpoint, or until the script terminates

When the Pause button is pressed, execution will stop where ever it was executing last. This can be a handy way to quickly profile your loops and see what instructions are taking the longest.

When the step button is pressed (f5 or f6), code execution will resume for one instruction. This is the most powerful feature to a new programmer. It allows you to see what your code is doing as it's doing it.


Ruby debuggers usually suck compared to other languages because... the last good debugger was based on a bug which was patched in ruby 1.9. But if you can use ruby 1.8.7, you can do expression watching and all that cool stuff.

So, click the lowest right button on the screen with a window and a plus sign. Select "expressions". Click and drag that to fit into the upper right window bay.

Click the "Create new Watch expression" button, and type years and click OK. You will now have a watch expression that is constantly watching the value of the variable years. If years is nil, it will say years = nil but when you hit f6 or click the step button, it will change to saying years = 2 once you step onto the instruction that sets the variable we're watching.

Let me know if you have any trouble with the instructions or any further questions.

View PostRedalin, on 06 October 2011 - 07:28 PM, said:

Also, where can I do some of this file manipulation that you speak of?

Some good projects to work on are usually projects that directly benefit you. I wrote some cool scripts back in the day that scanned a folder and wrote the names of all my songs and documents within that directory into a text file. I could run the script against the contents of a CD rom containing backups so I would have an inventory of everything on that disk and would be able to look things up later in the text file.

Little things like that are extremely rewarding and help you get to know a language fast without wasting too much of your time with devising discrete mathematics solutions that are usually only selected because they're easier to grade. When you're actually move 'physical' files around on your hard drive, or just reading them, it's a lot more enjoyable.
Was This Post Helpful? 2
  • +
  • -

#15 Redalin  Icon User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 23
  • Joined: 02-October 11

Re: Newbie: Nesting loops and getting results - wrong method?

Posted 07 October 2011 - 03:58 PM

I know what breakpoints are, but not how to set them -- but I'll be looking that up when I do another Ruby brainwash session tomorrow (8 hours of doing Ruby code) :detective: We really just go off Eclipse errors in the class, anything beyond that we haven't been taught (yet there's a debugging chapter in a few weeks).


Unfortunately, discrete mathematics solutions are all we've really worked with. All we're doing is scripting some games, which is a bit odd because I figured the course would be more focused on applications.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1