Ruby - Random Number is the Same Random Number, Every Time - ruby

wordList = ['1930', '1931', '1932', '1933', '1934', '1935', '1936', '1937', '1938', '1939', '1940']
wordLen = wordList.length
wordRand = rand(wordLen)
year = wordList[wordRand]
Very much a newb here... The behavior of year is such that every time I run the program, it selects a random string from wordList. The problem is that it takes that particular randomly-selected number and sets it as equal to year. So, for every instance of the program, year is the same string from the list each time I call it. How can I get it to select a different number each time?
puts 'Why hello there, dear! Grandma is, SO, happy to see you!'
response = gets.chomp
while response != 'BYE'
if response == response.upcase
puts 'NO, NOT SINCE ' + year + '!'
response = gets.chomp
else
puts 'WHAT? SPEAK UP, SONNY!'
response = gets.chomp
end
end
if response == 'BYE'
puts 'OKAY, BYE DEAR!!'
end
edit: added context

You appear to only be generating one value for year, then repeatedly using it in your loop. If you want different numbers, put the call to rand within the loop.

Related

Basic question Ruby; why is the total variable not updating in the loop

This code is supposed to update the total within the loop, but when I put the total when its broken it doesn't update.
total = 0
while true do
puts "Give me a number"
input = gets.chomp
if input == Integer
total += input
elsif input == "stop"
puts total
break
end
end
input = gets.chomp will result String class. So your logic on if input == Integer it will never be reached. you need to convert it to integer using to_i and input == Integer i never used that kind of syntax to check the classes, i rather use input.is_a?(String). but if you convert to integer first it will never check stop string condition. so maybe
total = 0
while true do
puts "Give me a number"
input = gets.chomp
if input == "stop"
puts total
break
end
total += input.to_i
end
As mentioned in the above comment by mu is too short and dedypuji's answer you have a couple of issue. Here is another variation that I think will work and I think is a little more ruby idiomatic.
total = 0
loop do
print "Give me a number: "
input = gets
break if /stop|^$/ =~ input
total += input.to_i
end
puts total

Simple program but so very stuck- Loops in Ruby

I have to write a program which asks the user to enter a number.
The program keeps on asking the user for a number until the user types 'Stop'
at which point the sum of the numbers that the user has entered should be printed.
I've tried many,many things and none of my ideas work.
This is what I have - but I can that it isn't correct. What am I doing wrong?
I've only used while loops and arrays
total_user_input = []
# As long as the user inputs a number, the program will keep putting Give me a number
# and then adding that number to the total_user_input array.
puts "Give me a number: "
while user_input = gets.chomp.to_i
#add the input to the array total_user_input
total_user_input.push(user_input.to_i)
puts "Give me a number: "
# If the user however types stop, then the loop is broken and we jump down to the
# sum bit - where all of the numbers in the total_user_input array are added together
# and printed. End of program!
if user_input == "stop"
break
end
sum = 0
total_user_input.each { |num|
sum += num
}
puts sum
end
The output isn't as it should be.
As others have identified the problems with your code let me suggest how you might reorganize it. Ruby provides many ways to execute loops but you many find it desirable to primarily relay on the method Kernel#loop and the keyword break. (As you will learn in time, loop is particularly convenient when used with enumerators.)
def sum_numbers
tot = 0
loop do
print 'Gimme a number: '
s = gets.chomp
break if s == 'Stop'
tot += s.to_i
end
tot
end
The keyword break can optionally take an argument (though why that is not mentioned in the doc I cannot say), in which case it (if a literal) or its value (if a variable or method) is returned by loop. Here one would generally see
break tot if s == 'Stop'
without the final line, tot. As the loop returns tot and that is the last calculation performed by the method, the method will return the final value of tot.
You could have instead written
return tot if user_input == 'Stop'
but I think most coders believe best practice dictates that one should not return from a method from within a loop (or from within nested loops) unless there is a good reason for doing so.
Some small points:
I used print rather than puts to that the user's entry will be shown on the same line as the prompt.
I used s (for "string") rather than user_input because it reduces the chance of spelling mistakes (e.g., user_imput), speeds reading, and (possibly a foible of mine), looks neater. True, s is not descriptive, but one only has to remember its meaning for three consecutive lines of code. Others may disagree.
You could write, break if s.downcase == 'stop' if you want, say, 'stop' or 'STOP' to have the same effect as 'Stop'.
'23O3'.to_i #=> 23 (that's an an oh, not a zero), so in real life you'd want to confirm that either 'Stop' or the string representation of a number had been typed.
This is how I would do this preferring to use loop do end syntax with a break when it should. Also added a bit more text so user knows what's happening.
total_user_input = []
puts 'Give me a number or "stop" to end: '
loop do
user_input = gets.chomp
total_user_input << user_input.to_i
puts "Give me a number: "
break if user_input.downcase == "stop"
end
puts "Total entered: #{total_user_input.inject(&:+)}" unless total_user_input.empty?
puts 'goodbye!'
Note these few things:
get.chomp.to_i will convert every input to integer. ("stop" or any non integer string will be 0)
Arrangement of the flow is quite messy.
total_user_input = []
puts "Give me a number: "
while user_input = gets.chomp.strip
total_user_input.push(user_input.to_i)
sum = 0
total_user_input.each { |num|
sum += num
}
puts sum
if user_input == "stop"
break
end
end
Hope you understand this.

unique rand number in a ruby loop

I am reading the book "Learn to program", and I have come across an exercise that I am having trouble with.
year = (rand(1900...1990))
while true do
puts "What would you like to say to grandma?"
ask = gets.chomp
if
ask == ask.downcase
puts "SPEAK UP SONNY"
elsif
ask == ask.upcase
puts "NO, NOT SINCE #{year}!"
end
break if ask == "BYE"
end
everything is functioning properly, but if the rand number "year" comes up more than once, it repeats the same number. Is there a way to have it become a unique random number each time it comes up during the same loop?
thank you in advance
Move year assignment into the loop to have it assigned before each chomp.
The value of year does not change within the loop because it is defined outside the loop. It would change if the definition were moved inside the loop, but you still may have years repeated. To fix both of these problems, change
year = rand(1900...1990)
to
years = (1900...1990).to_a.shuffle
(outside the loop) and change
puts "NO, NOT SINCE #{year}!"
to
puts "NO, NOT SINCE #{years.shift}!"
(or years.pop). If this is repeated more than 91 times an exception will be raised.

Naming a new file with timestamp?

I'm trying to write a simple command line program that lets me keep track of how many times I get distracted during a study session.
I'm getting an argument error when I run this code saying my file.open has invalid arguments. If I want to name each new_session file with a timestamp, what would be a simple solution?
def first_question
puts "Would you like to start a new session?"
answer = gets.chomp
answer = answer.downcase
if answer == "yes"
new_session
else
puts "Ok. Would you like to review a previous session?"
prev_session = gets.chomp
prev_session.downcase
if prev_session == "yes"
#GET AND REVIEW PREVIOUS SESSIONS
elsif prev_session == "no"
puts "Well if you don't want a new session, and you don't want to review your old sessions, then you're SOL."
else
"That's not an acceptable response."
first_question
end
end
end
def new_session
distractions = 0
d = File.open("Session"+Time.now.to_s , 'w'){|f| f.write(distractions) }
puts "What would you like to do (add track(s) or review tracks)?"
request = gets.chomp
request.downcase
if request == "add track"
distractions = distractions.to_i + 1
puts "You have #{distractions} tracks in this session."
elsif request == "add tracks"
puts "How many times have you been distracted since we last met?"
answer = gets.chomp
distractions = distractions.to_i + answer.to_i
puts "You have #{distractions} tracks."
elsif request == "review tracks"
puts distractions
end
File.open( d , 'w') {|f| f.write(distractions) }
end
first_question
Most of your code is messy and redundant. The problem you are referring to, though, comes from here:
d = File.open("Session"+Time.now.to_s , 'w'){|f| f.write(distractions) }
d will be the number of bytes written to the file and thus a Fixnum. You can't open a Fixnum which you're trying to do in the last line of the function.
Further,
request = gets.chomp
request.downcase
The second line here does nothing.
You have two File.open statements:
d = File.open("Session"+Time.now.to_s , 'w'){|f| f.write(distractions) }
and:
File.open( d , 'w') {|f| f.write(distractions) }
Your error code will tell you which one is wrong, but, from looking at them, I'd say it's the second one.
d will be assigned the result of the block for the first File.open, which is going to be the result of f.write(distractions):
The File.open docs say:
The value of the block will be returned from File.open.
The File.write docs say:
Returns the number of bytes written.
As a result, you are assigning d a number of bytes, then trying to create a file with an integer for a filename, which is an error because a filename MUST be a string.
That leads to a bigger problem, which is, your code makes no sense.
d = File.open("Session"+Time.now.to_s , 'w'){|f| f.write(distractions) } writes a 0 to the file created by "Session"+Time.now.to_s.
request.downcase converts the contents of request to lowercase and immediately throws it away. Perhaps you meant request.downcase!, but it'd be better to write:
request = gets.chomp
request.downcase
As:
request = gets.chomp.downcase
distractions = distractions.to_i + 1? distractions is already 0 which is a Fixnum. You're converting a Fixnum to an integer using to_i then adding 1 to it. Simply do:
distractions += 1
distractions = distractions.to_i + answer.to_i should be:
distractions += answer.to_i
File.open( d , 'w') {|f| f.write(distractions) }, because it's trying to write to a file with the integer name, won't update your original file. If it succeeded, it'd write to an entirely new file, which would end up overwriting the previously created file, which was the result of writing a single 0 to disk. Instead, d should be the name of the file previously created.
Consider this:
def new_session
distractions = 0
puts "What would you like to do (add track(s) or review tracks)?"
request = gets.chomp.downcase
case request
when "add track"
distractions += 1
puts "You have #{distractions} tracks in this session."
when "add tracks"
puts "How many times have you been distracted since we last met?"
distractions += gets.chomp.to_i
puts "You have #{distractions} tracks."
when "review tracks"
puts distractions
end
File.write( "Session" + Time.now.to_s, distractions)
end
This code is cleaner, and makes more sense now.

Why isn't my loop working?

I can't get this program to respond properly to user input. Various looping techniques either only run the block once or run the block infinitely no matter what the user inputs (I've tried case and while as well). Here's the most recent method I've tried:
work_summary = []
begin
# code that runs a sprint and adds results to the work_summary array
puts "Would you like to add a sprint, Y/N?"
sprint = gets.to_s
end until sprint == "N"
print work_summary, "\n"
Ruby never objects to my syntax with any of the various methods, but it also never works.
You need
sprint = gets.chomp
gets returns string with trailing "\n".
http://web.njit.edu/all_topics/Prog_Lang_Docs/html/ruby/syntax.html#begin
Begin is typically used for exception handling. I think you're looking for a while loop.
Here is an example
work_summary = []
while true
puts "Would you like to add a sprint?"
sprint = gets.chomp
if sprint == "N"
break
elsif sprint == "Y"
puts "What's your time?"
time = gets.chomp
work_summary << time
else
puts "I didn't understand your request. Enter Y or N"
end
end
I found two possibility over here which is suitable for you
First one is
while true
puts "Would you like to add a sprint?"
sprint = gets.chomp
if sprint == "N"
break
elsif sprint == "Y"
puts "What's your time?"
time = gets.chomp
work_summary << time
else
puts "Wrong request. Enter Y or N"
end
end
Here Lopp will run until break Doesn't get executed
Second thing you can Modify 1 Line in your code which is
sprint = gets.chomp
this will extract last special character of your string which is generated by gets and work fine in your case

Resources