Comparing a rand to a range of numbers? - ruby

Is there a function in Ruby that'll allow me to do what I'm attempting here?
rand1 = rand(10)
puts rand1
puts ""
if rand1 == (0..9)
print "yes"
else
print "no"
end
This prints out no, how could line 6 be altered so that this will print out yes?

You could use a case expression:
case rand
when 0..9
print 'yes'
else
print 'no'
end
It also allows you to provide multiple ranges or numbers to compare against. Here's a contrived example:
case rand
when 0..2, 3, 4..9
print 'yes'
else
print 'no'
end
Under the hood, case uses === to compare the given objects, i.e. the above is (almost) equivalent to:
if 0..2 === rand || 3 === rand || 4..9 === rand
print 'yes'
else
print 'no'
end
(note that the when objects become the receiver and rand becomes the argument)

You can use Range#cover? which works like === in this case.
irb(main):001:0> (0..9).cover?(0.1)
=> true

It's simple, use ===
rand1 = rand(10)
puts rand1
puts ""
if (0..9) === rand1
print "yes"
else
print "no"
end
Note: rand1===(0..9) won't work
And also you can use member?
rand1 = rand(10)
puts rand1
puts ""
if (0..9).member?(rand1)
print "yes"
else
print "no"
end

Not the best option but yet an option (not covered here: Determining if a variable is within range?)
rand1 >= (0..9).begin && rand1 <= (0..9).end
See Range docs, anyway: https://ruby-doc.org/core-2.6.5/Range.html#method-i-end

Related

What happen with a condition on a case?

I was playing today and accidentally end up writting this, now I'm courious.
i = 101
case i
when 1..100
puts " will never happen "
when i == 101
puts " this will not appear "
else
puts " this will appear"
end
How ruby internally process when i == 101 is like i == (i == 101) ?
Your code is equivalent to:
if (1..100) === 101
puts " will never happen "
elsif (101 == 101) === 101
puts " this will not appear "
else
puts " this will appear"
end
If we look at Range#=== we see that
(1..100) === 101
is equivalent to:
(1..100).include?(101)
#=> false
(101 == 101) === 101 reduces to:
true === 101
We see from the doc for TrueClass#=== that this is equivalent to:
true == 101
#=> false
Hence, the else clause is executed.
The structure
case a
when x
code_x
when y
code_y
else
code_z
end
evaluates identically to
if x === a
code_x
elsif y === a
code_y
else
code_z
end
Each when calls the method === on the argument of when, passing the argument of case as the parameter (x === a is identical to x.===(a)). The === method is slightly different than ==: it is typically called "case subsumption". For simple types like numbers and strings, it is the same thing as ==. For Range and Array objects, it is a synonym for .include?. For Regexp objects, it is quite similar to match. For Module objects, it tests whether the argument is an instance of that module or one of its descendants (basically, if x === a then a.instance_of?(x)). Thus, in your code,
if (1..101) === i
...
elsif (i == 101) === i
...
else
...
end
which performs pretty much the same tests as
if (1..101).include?(i)
...
elsif (i == 101) == i
...
else
...
end
Note that there is another form of case that does not employ ===:
case
when x
code_x
when y
code_y
else
code_z
end
which is identical to
if x
code_x
elsif y
code_y
else
code_z
end
If you do when i == 101 its equivalent to:
i == (i == 101)
which for your code is equal to
101 == true # false
if you do the when case as follows:
when i == 101 ? i : false
It will enter to that block section
i = 101
case i
when 1..100
puts " will never happen "
when i == 101 ? i : false
puts " THIS WILL APPEAR "
else
puts " this will now NOT appear"
end
#> THIS WILL APPEAR

what types of instructions can i put under (case) when statements?

What types of instructions can I put under when? Some of my code works under if/else, but does not work under case when.
For example
def categories(massIndex)
case massIndex
when >= 30.0
"obese"
#[some instructions like this]
else
"error"
end
end
I always see error like this:
bmi.rb:8: syntax error, unexpected >=
when >= 30.0
But when i do it with if/else, it works:
def categories(massIndex)
if massIndex >= 25
"something"
else
"error"
end
end
Can I fix it still using case, or must I use the if/else?
case x
when y
puts "y"
when z
puts "z"
end
is equivalent to
if y === x
puts "y"
elsif z === x
puts "z"
end
For example
case "hello"
when Array
puts "Array"
when String
puts "String"
end
#=> "String"
x = "hello"
if Array === x
puts "Array"
elsif String === x
puts "String"
end
#=> "String"
Note:
Array.method(:===).owner
#=> Module
String.method(:===).owner
#=> Module
See Module#===.
So when you write
case massIndex
when >= 30.0
"obese"
...
Ruby attempts to evaluate
(>= 30.0) === massIndex
causing her to raise a syntax error.
Here's another example that illustrates the usefulness of the method ===.
case "spiggot"
when /cat/ then "cat"
when /dog/ then "dog"
when /pig/ then "pig"
end
#=> pig
Since
/cat/.method(:===).owner
#=> Regexp
see Regexp#===.
Here is an excellent article about the case statement.
case
when massIndex >= 30.0
"obese"
[some instructions like this]
else
"error"
end

Ruby: Reverse method from scratch

I'm working on a coding challenge practice problem that is asking me to put together a method that reverses a string and have come up with:
def reverse(string)
idx = 1
array_s = []
while idx <= string.length
array_s.push(string[string.length - idx])
idx = idx + 1
end
new_string = array_s.join("")
puts new_string
end
When I run the test given at the end,
puts(
'reverse("abc") == "cba": ' + (reverse("abc") == "cba").to_s
)
puts(
'reverse("a") == "a": ' + (reverse("a") == "a").to_s
)
puts(
'reverse("") == "": ' + (reverse("") == "").to_s
)
it seems to show that the strings reverse, but it still prints false. Is there anything I'm missing in the method I wrote? Thanks.
Your function is working as expected, it is the last line that is causing you issues.
puts new_string
puts returns nil, ruby uses implicit returns unless you explicitly say return, so it returns the result from the last line of code, in this case is nil.
If you just do new_string or return new_string, it will work.
Or if you want to print it to the screen and return it as the result, you can do
p new_string
davidhu2000 has answered your question correctly but i would suggest refactoring the code:
f = "forward"
puts f.reverse
# drawrof
of if you really want:
def reverse(string)
return string.reverse
end

undefined method (NoMethodError) ruby

I keep getting the following error message:
text.rb:2:in `<main>': undefined method `choices' for main:Object (NoMethodError)
But I can't seem to understand why my method is "undefined":
puts "Select [1] [2] [3] or [q] to quit"; users_choice = gets.chomp
choices(users_choice)
def choices (choice)
while choice != 'q'
case choice
when '1'
puts "you chose one!"
when '2'
puts "you chose two!"
when '3'
puts "you chose three!"
end
end
end
This is because you are calling method choices, before defining it. Write the code as below:
puts "Select [1] [2] [3] or [q] to quit"
users_choice = gets.chomp
def choices (choice)
while choice != 'q'
case choice
when '1'
break puts "you chose one!"
when '2'
break puts "you chose two!"
when '3'
break puts "you chose three!"
end
end
end
choices(users_choice)
I used break, to exit from the while loop. Otherwise it will create an infinite loop.
def main
puts "Select [1] [2] [3] or [q] to quit"; users_choice = gets.chomp
choices(users_choice)
end
def choices (choice)
while choice != 'q'
case choice
when '1'
puts "you chose one!"
break
when '2'
puts "you chose two!"
break
when '3'
puts "you chose three!"
break
end
end
end
main
The method only needs to be called prior to being executed. Here I wrap the definition in the main method, but only call main after the definition of choices().
I was getting the same error running Ruby in Eclipse working out the App Academy practice exercises. I forgot to add "object." to the supplied test cases. The following syntax works:
#!/usr/bin/ruby
class Prime
# Write a method that takes in an integer (greater than one) and
# returns true if it is prime; otherwise return false.
#
# You may want to use the `%` modulo operation. `5 % 2` returns the
# remainder when dividing 5 by 2; therefore, `5 % 2 == 1`. In the case
# of `6 % 2`, since 2 evenly divides 6 with no remainder, `6 % 2 == 0`.
# More generally, if `m` and `n` are integers, `m % n == 0` if and only
# if `n` divides `m` evenly.
#
# You would not be expected to already know about modulo for the
# challenge.
#
# Difficulty: medium.
def primer(number)
if number < 2
return false
end
i = 10
while i > 1
if number > i && number != i
if number % i == 0
return false
end
end
i -= 1
end
return true
end
end
object = Prime. new
# These are tests to check that your code is working. After writing
# your solution, they should all print true.
puts("\nTests for #primer")
puts("===============================================")
puts('primer(2) == true: ' + (object.primer(2) == true).to_s)
puts('primer(3) == true: ' + (object.primer(3) == true).to_s)
puts('primer(4) == false: ' + (object.primer(4) == false).to_s)
puts('primer(9) == false: ' + (object.primer(9) == false).to_s)
puts("===============================================")

Trying to go to a certain step after its completed one in ruby

Alright. I want it so the following would happen, Heres a sample:
puts "what would you like to see?"
var = gets.chomp
if var == "z"
puts "this"
elsif var == "d"
puts "stack"
elsif var == "y"
puts "overflow"
else
puts "I don't understand that."
end
Currently it works fine up until I want to have the user redefine the 'var'. Currently all the loops just loop back the puts from the elsif - i want it to ask for the user input again, then print out the elsif to that.
For example:
User types in y, the code would say overflow, then return to line 1. Any help would be awesome.
gets returns nil when there is no input, and since nil evaluates to false in a conditional, you can use gets in a loop like so
while var = gets
var.chomp!
if var == "z" # use == to test equality, not =
# do stuff
elsif var == "x"
# do stuff
....
end # while
You might find this works better with a case statement:
while var = gets
case var.chomp
when "z"
puts "this"
when "d"
puts "stack"
when "y"
puts "overflow"
else
puts "I don't understand that."
end # case
end # while
You're using the assignment operator (=) where you mean to test equality (==), I think.
You could also use case, but here's a version with while and if
print "Gimme an answer ('q' to quit) >> "
response = gets.chomp
while response != 'q'
if response == 'z'
puts "this"
elsif response == 'd'
puts "stack"
elsif response == 'y'
puts "overflow"
else
puts "I don't understand that."
end
print "Gimme another answer ('q' to quit) >> "
response = gets.chomp
end

Resources