Misbehaving Case Statement - ruby

I'm messing around in Ruby some more. I have a file containing a class with two methods and the following code:
if __FILE__ == $0
seq = NumericSequence.new
puts "\n1. Fibonacci Sequence"
puts "\n2. Pascal\'s Triangle"
puts "\nEnter your selection: "
choice = gets
puts "\nExcellent choice."
choice = case
when 1
puts "\n\nHow many fibonacci numbers would you like? "
limit = gets.to_i
seq.fibo(limit) { |x| puts "Fibonacci number: #{x}\n" }
when 2
puts "\n\nHow many rows of Pascal's Triangle would you like?"
n = gets.to_i
(0..n).each {|num| seq.pascal_triangle_row(num) \
{|row| puts "#{row} "}; puts "\n"}
end
end
How come if I run the code and supply option 2, it still runs the first case?

Your case syntax is wrong. Should be like this:
case choice
when '1'
some code
when '2'
some other code
end
Take a look here.
You also need to compare your variable against strings, as gets reads and returns user input as a string.

Your bug is this: choice = case should be case choice.
You're providing a case statement with no "default" object, so the first clause, when 1, always returns true.
Effectively, you've written: choice = if 1 then ... elsif 2 then ... end
And, as Mladen mentioned, compare strings to strings or convert to int: choice = gets.to_i

Related

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.

Loop error for multiple conditions

I have this loop:
puts "Welcome to the Loop Practice Problems"
puts " Write a number between 1 and 10, but not 5 or else...."
ans = gets.chomp!
if ans < 1
puts "Tf bruh bruh"
elsif ans > 10
puts "Now you just playin"
elsif x == 5
print "You wildin B"
else
puts "Fosho that's all I require"
end
It doesn't run properly, and I'm trying to understand why. If you can help me with this, I'd appreciate it.
If you know a good site for practice problems, I'd love to try it. I checked out Coderbyte and Code Kata, but the way they're set up doesn't look right, and they don't have questions to solve for fundamentals.
The issue here is that you're not converting ans to a number, but you're comparing it to one. ans is going to be a string.
In Ruby, when you compare a number to a string, Ruby says that the two aren't equal:
"1" == 1
=> false
You can reproduce the problem with this code:
puts "Welcome to the Loop Practice Problems"
puts " Write a number between 1 and 10, but not 5 or else...."
ans=gets.chomp!
p ans
The p method will output an "inspected" version of that object, (it's the same as doing puts ans.inspect). This will show it wrapped in quotes, which indicates that it's a string.
You probably want to do this:
ans = gets.chomp!.to_i
The to_i method here will convert the number to an integer, and then your comparisons will work correctly.
You have to convert input string type object into integer type
ans = gets.chomp!.to_i #input string convert into integer.
if ans < 1
puts "Tf bruh bruh"
elsif ans > 10
puts "Now you just playin"
elsif x == 5
print "You wildin B"
else
puts "Fosho that's all I require"
end

returning the sum of a users input until they say stop

I am trying to create something that constantly takes a users input until they say stop. Then, add all of the previous numbers together. This is what I have so far:
arr = []
puts "Give me a number:"
while input = gets.chomp
if input == "stop"
break
else
puts "Give me a number:"
arr << input
end
end
sum = arr.inject(:+)
puts sum
This is working fine up until adding the numbers together. The arr.inject(:+) seems to be joining the numbers together rather than adding.
For example, when in the while loop, I am entering 1, 2 and 3 into the gets.chomp, but the program is returning 123 rather that 6.
Where am I going wrong?
arr.inject(0) { |sum,e| sum + e.to_i }
a bit more verbose but your problem is that reading from input == String and you want Integer.
Other solution could be
arr.map(&:to_i).inject(:+)
But the first one is more efficient but less fancy.
It is the combination of
arr << input
and
arr.inject(:+)
For example, if you change the first one to:
arr << input.to_i
then it would not be wrong any more.

Program to take input from command line into an array and find the biggest among them

I am new to Ruby and just can't figure out how you take input for an array from a user and display it.If anyone could clear that I can add my logic to find the biggest number.
#!/usr/bin/ruby
puts "Enter the size of the array"
n = gets.chomp.to_i
puts "enter the array elements"
variable1=Array.new(n)
for i in (0..n)
variable1[i]=gets.chomp.to_i
end
for i in (0..n)
puts variable1
end
How about capturing the array in one line?
#!/usr/bin/ruby
puts "Enter a list of numbers"
list = gets # Input something like "1 2 3 4" or "3, 5, 6, 1"
max = list.split.map(&:to_i).max
puts "The largest number is: #{max}"
You are doing it ok. But try this little change
#!/usr/bin/ruby
puts "Enter the size of the array"
n = (gets.chomp.to_i - 1)
puts "enter the array elements"
variable1=Array.new(n)
for i in (0..n)
variable1[i]=gets.chomp.to_i
end
puts variable1
or for undefined number of values here is one way
#!/usr/bin/ruby
puts "enter the array elements (type 'done' to get out)"
input = gets.chomp
arr = []
while input != 'done'
arr << input.to_i
input = gets.chomp
end
puts arr
I believe that this is a little bit more elegant solution.
puts "Please enter numbers separated by spaces:"
s = gets
a = s.split(" ")
#Displays array
puts a
#Displays max element
puts a.max
First you collect the series of numbers from the user, then you use a split method on the string, which converts it to the array. If you want to use some other separator, like "," than you can write s.split(","). After that you can use your logic to find the biggest number or you could just use max method.
Some feedback:
chomp.to_i is a bit redundant, since the latter will also remove newlines.
for x in y is not commonly seen in idiomatic Ruby code. It basically behaves like each with slightly different scoping rules and probably should have been removed from the language a while ago.
Ruby arrays are dynamic, so no need to preinitialize them. Something like (1..n).map { gets.to_i } would also produce the array you need.
Displaying it can then be done like this: array.each { |n| puts n }
Alternatively you can use the strip approach outlined before, take the numbers as command line arguments in ARGV or pipe into your program using ARGF.

How Do You Put 'gets' Input Into An Array?

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

Resources