I have a task to puts an infinite number of word, each in one line to array, and when enter is pressed on an empty line, puts these words in reverse order. How can I define when enter is pressed or empty line is input?
Code is here:
word = []
puts "Enter word"
add = 0
until add == ????
word.push gets.chomp
add = word.last
end
puts word.reverse
Here's a possible solution, with comments. I didn't see any useful role being played by your add variable, so I ignored it. I also believe in prompting the user regularly so they know the program is still engaged with them, so I moved the user-prompt inside the loop.
word = [] # Start with an empty array
# Use loop when the terminating condition isn't known at the beginning
# or end of the repetition, but rather it's determined in the middle
loop do
print 'Enter word: ' # I like to prompt the user each time.
response = gets.chomp # Read the response and clean it up.
break if response.empty? # No response? Time to bail out of the loop!
word << response # Still in the loop? Append the response to the array.
end
puts word.reverse # Now that we're out of the loop, reverse and print
You may or may not prefer to use strip rather than chomp. Strip would halt if the user input a line of whitespace.
Here, this is a modified version of your code and it works as requested.
word = []
puts "Enter word"
add = 0
while add != -1
ans = gets.chomp
word.push ans
if ans == ""
puts word.reverse
exit
end
add += 1
end
puts word.reverse
This is another version, using (as you did originally) the until loop.
word = []
puts "Enter word"
add = 0
until add == Float::INFINITY
ans = gets.chomp
word.push ans
if ans == ""
puts word.reverse
exit
end
add += 1
end
puts word.reverse
Related
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.
I am currently working on building a word guessing game. There is a word and a user would guess a character in the word. If the character the user guesses is in fact in the word then feedback would be given back. For example the word is "cookie" and the user enters "o" then feedback would be
_ o o _ _ _
the number of attempts is equal to the length of the word in this case 6. If the user guesses a character that is not part of the word for example "z" a message would display error. However I am having problems accessing the if and else statements, they work only for the first input. here is my code:
class Game
attr_reader :word
attr_accessor :guess_counts, :guesses, :user_input, :guess_array
def initialize(word)
#word = word
#guesses = ""
end
def tries
#tries = #word.length
end
def guesses(user_input)
#user_input = user_input
#guesses << #user_input
end
def underscored
return #word.tr('^' + #guesses, '_').chars.join(' ')
end
end
# user interface
puts "Please enter a word to initialize the Guessing The Word game"
secret_word = gets.chomp
game = Game.new(secret_word)
puts "you have #{game.tries} attemps left"
guesses = []
tries = secret_word.length
while tries > 0
puts "Plese enter a letter you believe is in the secret word"
letter = gets.chomp
game.guesses(letter)
guesses << letter
guess = guesses[0]
if !secret_word.include? guess
puts "Letter not in word"
tries -= 1
puts "you have #{tries} left "
next
elsif secret_word.include? guess
p game.underscored
else
puts "you lost"
end
end
as you see in this image when I input "o" it says letter not in word but if I start with the letter "o" it would display
The problem is you are always grabbing the first element in the array of guesses when you wrote:
guess = guesses[0]
So the expression !secret_word.include? guess is:
always true when the first guess is correct, and then is
always false when the first answer is incorrect
To fix this you probably want grab the last guess; ie.
guess = guesses.last
# `.last` is convenience method for accessing last element of an array; like so
#
# guess = guesses[-1]
or the current letter for your if statement: i.e.
if !secret_word.include? letter
# [...]
elsif secret_word.include? letter
# [...]
I'm learning Ruby with 'Learn to Program' by Chris Pine. On chapter 10 I should write a program where the user types as many words as he like and when he's done, he can just press Enter on an empty line and exit.
I came up with this:
puts "Type whatever you want!"
index = 0
word = ''
array = []
while word != nil
word << gets.chomp
array[index] = word
index = index + 1
end
puts ''
puts array.sort
But that doesn't work. What did I miss? Is there another way I could define word without having to repeat it?
The word will not have nil value. It will be an empty string. So you need to check for that:
while word != ""
# or even better
while !word.empty?
Also, you are adding everything to your word. You probably want to assign to it instead:
word = gets.chomp
Per author's comment:
begin
# your code here
end while !word.empty?
# OR more readable
begin
# your code here
end until word.empty?
It seems like there's a simpler solution, if I'm reading the question correctly.
You could do something like this:
user_input = gets.chomp.split(" ").sort
ex)
input: bananas clementine zebra tree house plane mine
output: ["bananas", "clementine", "house", "mine", "plane", "tree", "zebra"]
Here's a simple loop that you could do just for kicks:
arr = []
arr << $_.strip until gets =~ /^\s*$/
puts arr.sort
$_ is a special variable that evaluates to the last input read from STDIN. So basically this reads "Call gets and check if the input is just spaces. If it is then break out of the loop, otherwise append the last input with whitespace removed value onto the array and continue looping."
Or even more fun, a one liner:
puts [].tap {|arr| arr << $_.strip until gets =~ /^\s*$/}.sort
Basically same thing as above except using tap to initialize the variable.
To answer your questions:
Is there another way I could define word without having to repeat it?
Use side effects of assignment. In ruby when you assign a variable the return value of that assignment is the assigned variable, as in:
irb(main):001:0> (variable = 2) == 2
=> true
The idea would be to put the assignment in the your conditional. If I were to write something like this in a comprehensible loop, as opposed to those above, I'd write something like this:
arr = []
while !(word = gets.strip).empty?
arr << word
end
puts arr.sort
Using loop might simplify the code:
a = []
loop do
input = gets.chomp
if input.empty?
break
else
a << input
end
end
a.sort!
puts a
Is there a way to make this code shorter and simpler?
loop do
if possibleSet.split(" ").map(&:to_i).any? {|e| (e<0 || e>12)}
print "Please enter valid numbers (between 1 and 12): "
possibleSet = gets
errorinput = false
else
errorinput = true
end
break if errorinput
end
Refactored a bit :)
loop do
print "Please enter valid numbers (between 1 and 12): "
possibleSet = gets.chomp
break unless possibleSet.split(" ").map(&:to_i).any? {|e| (e<0 || e>12)}
end
The code below will check input for correctness:
input = loop do
print "Please enter valid numbers (between 1 and 12): "
# ⇓⇓⇓ as many spaces as user wants
input = gets.chomp.split(/\s+/).map(&:to_i) rescue []
break input unless input.empty? || input.any? { |i| !(0..12).include? i }
end
This parses the user input in an array (not exactly the same behavior, but I hope it is cleaner and you can work from there)
set = []
until set.all? {|i| (1..11).include?(i) } && !set.empty? do
set = gets.split(' ').map(&:to_i)
end
Ruby noob here learning the ropes. I'm currently going through this tutorial and am working on this exercise:
Let's write a program which asks us to
type in as many words as we want (one
word per line, continuing until we
just press Enter on an empty line),
and which then repeats the words back
to us in alphabetical order.
I'm ignoring the alphabetical order part, for now.
Here is my code:
puts 'Hi, do you need something sorted?'
yn = gets.chomp
while yn != 'no'
puts 'What else?'
array = [gets]
yn = gets.chomp
end
puts 'Here\'s what you told me: ' +array.to_s
I've tweaked this for a few hours. To prevent my laptop from breaking due to an act of frustration I'm taking a break. Can anybody with more experience, and possibly more patience, point out my errors?
Keep in mind that every time you gets is a method that asks the user for input. On your lines:
array = [gets]
yn = gets.chomp
You are actually asking for input twice. Instead, store the user input somewhere (such as the array, see below) and get the stored value rather than asking the user twice.
Further, array = [gets] replaces the existing array with an array containing one element (the user input). You are never building up user input into the array. Instead, initialize the array before the while loop and use << in the loop:
array = Array.new
...
while yn != "no"
...
array << gets.chomp
yn = array.last
...
end
If you're having difficulty with something, the first thing you should do is try something simpler.
Rather than doing gets and looping, just try doing a simple gets.
puts 'Hi, do you need something sorted?'
yn = gets.chomp
Then I'd see if yn was what I expected.
The next thing I'd do is, rather than doing a loop many times, just try it once
puts 'Hi, do you need something sorted?'
yn = gets.chomp
if yn != 'no'
puts 'What else?'
array = [gets]
yn = gets.chomp
STDERR.puts "array is #{array.inspect}"
STDERR.puts "yn is #{yn.inspect}"
end
Then you'd hopefully realize that array and yn are both getting input, which wouldn't make sense.
For more hints on how to debug Ruby code, see How do I debug Ruby scripts?
I was having the same problem. Here is where I ended up (I think it meets all the specifications from the question):
puts 'Type in as many words as you\'d like. When you\'re finished, press enter on an empty line'
array = []
input = ' '
while input != ''
input = gets.chomp
array.push input
end
puts
puts array.sort
while yn != "no"
array << yn
print "What else? "
yn = gets.chomp
end
The "<<" appends yn to your array. (The only reason I used print is because it puts the cursor right next to the question mark instead of on the next line. No other reason)
#encoding:utf-8
x = Array.new
puts "enter something:".capitalize
y = ''
while y !=#nill
y = gets.chomp
x.push y
end
x.delete ('')
x.compact
puts "You entered: " + x.sort.to_s
puts "Objects in array: " + x.size.to_s
#made by ~Pick#chu!!!
Another way to read ‘Arrays’ from the console could be:
1: print “enter the values: ”
2: a = gets.chomp # input: “tom mark rosiel suresh albert”
3: array = a.split(‘ ‘) # .split() method return an array
4: p array # ["tom, "mark, "rosiel", "suresh", "albert"]
now, lets say you want an array of integers, all you have to do is:
# input “1 2 3 4 5″
3: array = a.split(‘ ‘).map{ |value| value.to_i }
4: p array # [1, 2, 3, 4, 5]
the clue here is to use a standard separator in order to use the .split() function.
here is how I've done this program:
array = [ ]
input = gets.chomp
while
input != ''
array.push input
input = gets.chomp
end
puts array
puts
puts array.sort