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
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
I would like to loop 20 times over an if statement, but each time it's run, some things must change.
Example:
input = [0,0,0,44,754,22,0,632,2,22,0,2,nil,2,24,nil,666,90909,2,4,6,7,2,7,3,2,2,7,1,8,6,3,2,19,5,46]
Statement = "Statement THIS"
if
input[1] != nil &&
input[2] == 0
Statement.sub! "THIS", "WHERE #{input[8]} #{input[9]} THIS"
else
end
puts Statement #Statement WHERE 2 22 THIS
if
input[5] != nil &&
input[6] == 0
Statement.sub! "THIS", "AND #{input[12]} #{input[13]} THIS"
else
end
puts Statement #Statement WHERE 2 22 AND 2 THIS
if
input[9] != nil &&
input[10] == 0
Statement.sub! "THIS", "AND #{input[16]} #{input[17]} THIS"
else
end
puts Statement #Statement WHERE 2 22 AND 2 AND 666 90909 THIS
In the second IF statement the following things have changed:
Each key has increased by 4 (1,2,8,9 became 5,6,12,13)
The word WHERE has changed to AND
I would like this behaviour to repeat another 18 times, so the third IF statement has:
Each key has increased by 4 (5,6,12,13 became 9,10,16,17)
The word HELLO has changed to GOODBYE (however this rule is now redundant, since the second IF statement took care of it).
input = [
0,0,0,44,754,22,0,632,2,22,0,2,
nil,2,24,nil,666,90909,2,4,6,7,
2,7,3,2,2,7,1,8,6,3,2,19,5,46
]
(1..Float::INFINITY).step(4) do |i|
i = i.to_i # is float here
break Statement if i >= input.size
next if input[i].nil? || !input[i+1].zero?
keyword = Statement =~ /WHERE/ ? 'AND' : 'WHERE'
Statement.sub! "THIS", "#{keyword} #{input[i+7]} #{input[i+8]} THIS"
end
#⇒ "Statement WHERE 2 22 AND 2 AND 666 90909 THIS"
To loop 20 times you can use the times method.
arr_index = 1
20.times do
if arr_index < 1
operator = "WHERE"
else
operator = "AND"
end
if input[arr_index] != nil && input[arr_index + 1] == 0
Statement.sub! "THIS", "#{operator} #{input[arr_index + 7]} #{input[arr_index + 8]} THIS"
end
arr_index += 4
end
Another option would be to change the contents of your input array or create another data structure (e.g., hash, array, array of hashes, hash of arrays) with the exact values you need for the loop. Thus, eliminating the need to increment the index by 4 at each iteration.
Also, unless Stamement is a class or a constant, convention dictates its name should be lower case (e.g., statement).
Good luck!
n = 20
"STATEMENT WHERE %s THEN" % (1..1+4*(n-1)).step(4).with_object([]) { |i,a|
a << "#{ input[i+7] } #{ input[i+8] }" unless input[i].nil? || input[i+1] != 0 }.
join(" AND ")
#=> "Statement WHERE 2 22 AND 2 AND 666 90909 THEN"
I need help on Writing a method that takes a string in and returns true if the letter "z" appears within three letters after an "a". You may assume that the string contains only lowercase letters. here's what I have:
def nearby_az(string)
string.downcase!
i = 0
while i < string.length
if (string[i] == "a" && string[i] == "z")
true
else
false
end
end
end
puts('nearby_az("baz") == true: ' + (nearby_az('baz') == true).to_s)
puts('nearby_az("abz") == true: ' + (nearby_az('abz') == true).to_s)
puts('nearby_az("abcz") == true: ' + (nearby_az('abcz') == true).to_s)
puts('nearby_az("a") == false: ' + (nearby_az('a') == false).to_s)
puts('nearby_az("z") == false: ' + (nearby_az('z') == false).to_s)
puts('nearby_az("za") == false: ' + (nearby_az('za') == false).to_s)
A regular expression would be the best for this. Try
def nearby_az(string)
(string =~ /a.{0,2}z/) != nil
end
EDIT:
as per the "if statement required requirement" :)
def nearby_az(string)
if (string =~ /a.{0,2}z/) != nil
return true
end
return false
end
The way this code works is it searches the input string for an "a". After that, the period indicates that you can have any character. After that you have {0,2} which is a modifier of the period indicating you can have 0 to 2 of any character. After this you must have a "z", and this fulfills your must have a z within 3 characters of an "a".
I've saved this regex to regex101 here so you can try various inputs as well as change the regular expression around to understand it better.
To fix you code you need to:
increment i at the end of the loop.
search the z letter within the 3 next letters
return true when condition is met
return false when getting out of the loop
Here is what it should look like:
def nearby_az(string)
string.downcase!
i = 0
while i < string.length do
return true if string[i] == "a" && string[i+1,3].include?(?z)
i+=1
end
return false
end
I wrote a tic-tac-toe program. The problem I am experiencing is that in my if statement, which allows the user enter his/her desired coordinate, my else condition is not working. The else condition is in place in case the user enters a coordinate not on the board.
This is my code:
class Game
def initialize
#board=Array.new
#board[1]="1 __|"
#board[2]="__"
#board[3]="|__"
#board[4]="\n2 __|"
#board[5]="__"
#board[6]="|__"
#board[7]="\n3 |"
#board[8]=" "
#board[9]="| "
#turn="o"
#win_status = false
end
def turn
#turn
end
def show_board
puts " 1 2 3"
#board.each do |i|
print i
end
puts ""
end
def set_turn #switches turns
if #turn == "x"
#turn = "o"
else #turn == "o"
#turn = "x"
end
end
def make_move
puts "Enter x coordinate"
x=gets.to_i
puts "Enter y coordinate"
y=gets.to_i
if y==1 && x==1
#board[1]="1 _"+#turn+"|"
elsif y==2 && x==1
#board[2]="_"+#turn
elsif y==3 && x==1
#board[3]="|_"+#turn
elsif y==1 && x==2
#board[4]="\n2 _"+#turn+"|"
elsif y==2 && x==2
#board[5]="_"+#turn
elsif y==3 && x==2
#board[6]="|_"+#turn
elsif y==1 && x==3
#board[7]="\n3 "+#turn+"|"
elsif y==2 && x==3
#board[8]=" "+#turn
elsif y==3 && x==3
#board[9]="| "+#turn+" \n"
else
"You entered an invalid coordinate"
end
end
def win_combo
return [[#board[1][4] + #board[2][1] + #board[3][2]], [#board[4][5] + #board[5][1] + #board[6][2]], [#board[7][5] + #board[8][1] + #board[9][2]],[#board[1][4] + #board[4][5] + #board[7][5]], [#board[2][1] + #board[5][1] + #board[8][1]], [#board[3][2] + #board[6][2] + #board[9][2]], [#board[1][4] + #board[5][1] + #board[9][2]], [#board[3][2] + #board[5][1] + #board[7][5]]]
end
def check_win
#if some row or column or diagonal is "xxx" or "ooo" then set #win_status = true
self.win_combo.each do |arr|
str = arr.join
if str == "xxx"
puts "X Wins!"
return true
elsif str == "ooo"
puts "O Wins!"
return true
end
end
return false
end
g = Game.new
while g.check_win != true
g.show_board
g.set_turn
g.make_move
end
end
You are just returning the string: "You entered an invalid coordinate".
I suspect that you want to display it using:
puts "You entered an invalid coordinate"
Otherwise it is passed as the result of g.make_move and then ignored.
I'm assuming you would like to print: "You entered an invalid coordinate" to the console in the event of an invalid x, y coordinate. You need to add a method to that statement like:
else
puts "You entered an invalid coordinate"
end
Or:
else
abort "You entered an invalid coordinate"
end
It looks you you forgot to use puts or print in front of your "You entered an invalid coordinate" string. As it is currently written it is returned from the method.
In Ruby, the return value of a method is the value returned by the last statement evaluated. For example, both of these methods will return the same value if x=3:
def square_example(x)
if x ==3
x_squared = 9
end
end
def square_example2(x)
if x == 3
x_squared = 9
end
return x_squared
end
For simplicity of testing you might try using explicit returns so that you can easily tell what it is you are returning from the method. Or (as a beginner with Ruby myself) you could add in a puts statement with each if/else result so that you can easily monitor the results of each move and then remove those puts lines when you know everything is working properly.
Looks like this is a misinterpretation of the site below, but if you're interested in the difference between 'and' and '&&' you should check out the comments below.
From: http://www.tutorialspoint.com/ruby/ruby_operators.htm
You will want to use "and" instead of "&&", an example:
if y==1 and x==1
# do move
elsif y==2 and x==1
# do move
.
.
.
else
"invalid coordinate"
end
The "&&" operator will check that the values on either side of it are nonzero. If they are both nonzero then it will return true. In your case it is doing the operation
false && false
Where false != 0, so it returns true.
Here is another discussion of this: http://archive.railsforum.com/viewtopic.php?id=27353