Breaking an until loop once condition is met in Ruby - ruby

For example in the following code, I would want the loop to end as soon as the condition evaluates as true
x = "B"
until x == "A"
x = gets.chomp
puts "x is not equal to "A""
end
So if the user enters "F" they get the puts but if they enter "A" then the puts does not get outputted.

x = true assigns true to x so until x = true is equivalent to until true.
So, replace = with == in the following line:
until x = true
->
until x == true
Or, it will never end.
UPDATE
Use following code:
while true
x = gets.chomp
break if x == 'A'
puts 'x is not equal to "A"'
end
or
until (x = gets.chomp) == 'A'
puts 'x is not equal to "A"'
end

The keyword break will exit from a loop.
x = false
a = 0
b = 0
until x # is a boolean already so no need for == true
a = 1
b = 2
# code here that could change state of x
break if x # will break from loop if x == anything other than false or nil
a = 2
b = 1
end
Obviously, this is not good code but there is some useful concepts in there that you might be able to fish out.
EDIT
In response to your new code, it is proper use for until loop.
puts "x is not equal to 'A'" until (x = gets.chomp) == "A"

Related

Ruby Number Guessing Game

I have tried to make a number guessing game using ruby but it seems to be looping all over again after the user gets the correct answer, here's my code and thanks in advance!
require './input_functions'
def check (rno,input)
x = 1
while (x == 1)
y = 0
if (rno > input)
puts("Try a bigger number")
input = gets.chomp.to_i
y = y + 1
x = 1
else
if (rno < input)
puts("Try a smaller number")
input = gets.chomp.to_i
y = y + 1
x = 1
else
if(rno == input)
puts("Bingo!")
x = 0
end
end
end
end
return
end
def main
rno = rand(100)
input = read_integer("Enter an integer between 0 and 100: ")
check(rno,input,y)
times = check(rno,input,y)
puts ("You have tried " + times.to_s + " times.")
end
main
The main problems are:
You call check method two times within main method, you need to remove the first one.
You need to move y = 0 out of while loop to be able to return it.
Tried to simplify your code a bit, and you could try to improve it even more.
def check(rno, input)
x = 1
y = 0
while x == 1
if rno == input
puts "Bingo!"
x = 0
else
if rno > input
puts "Try a bigger number"
else
puts "Try a smaller number"
end
input = gets.chomp.to_i
y = y + 1
end
end
return y
end
def main
rno = rand(100)
input = read_integer("Enter an integer between 0 and 100: ")
times = check(rno, input)
puts ("You have tried " + times.to_s + " times.")
end

Create a variable with value a boolean

I want to know if I can create a variable with a boolean as value, something like this:
my_var =
if X > Y
print "The value is true"
else
print "The value is false"
end
This is so I can write a boolean easily.
EDIT:
I'm trying to do "shortcuts" using variables that are equal to a boolean. That way, if I require to write a boolean multiple times in a code, I can just "call" the variable.
Example:
x = gets.chomp
y = gets.chomp
required_boolean =
if x > y
puts "x is greater than y"
elsif x = Y
puts "X and Y are equal"
else
puts "y is greater than x"
end
puts "Since x has a value of #{x} and y has a value of {y}, we can say that #{required_boolean}"
boolean in ruby supports #to_s..
Which means you can do something like this:
true.to_s # => "true"
false.to_s # => "false"
(1 < 2).to_s # => "true"

Unexpected Ruby behavior when instantiating two instances on one line

I created a class that generates a different name for each instance, but a test fails unexpectedly when instantiating two instances in one statement.
Here is the class.
class Robot
attr_accessor :name
##current_name = 'AA000'
def initialize
#name = ##current_name
##current_name.next!
end
end
Here the class behaves as expected
irb(main):009:0> Robot.new.name
=> "AA001"
irb(main):010:0> Robot.new.name
=> "AA002"
Here is the unexpected behavior, I was expecting false. This code is in a test on an exercise I am trying to get passing, so I can't change the test.
irb(main):011:0> Robot.new.name == Robot.new.name
=> true
Checking the object_id reveals that two different instances are being created.
irb(main):012:0> Robot.new.object_id == Robot.new.object_id
=> false
Why is Ruby doing this, what should I do to fix it & assuming there is a term for this, what could I have typed into search to find answered questions about this.
See if this helps:
class Robot
attr_accessor :name
##current_name = 'AA000'
def initialize
#name = ##current_name
##current_name.next!
end
end
x = Robot.new
puts x.name
y = Robot.new
puts y.name
puts x.name == y.name
puts x.name
puts y.name
--output:--
AA001
AA002
true
AA002
AA002
Why is Ruby doing this
Because each instance's #name variable refers to the same String as the variable ##current_name, and you keep changing that String with the ! method.
what should I do to fix it
class Robot
attr_accessor :name
##current_name = 'AA000'
def initialize
#name = ##current_name.dup
##current_name.next!
end
end
x = Robot.new
puts x.name
y = Robot.new
puts y.name
p x.name == y.name
p x.name
p y.name
--output:--
AA000
AA001
false
AA000
AA001
Although, I and many other people will warn you NEVER to use ##variables in your code.
Ruby assignment operator:
1. x = “hello”:
x ------> “hello”
2. y = x:
x ------> “hello”
^
|
y -----------+
3. y << “ world”:
x ------> “hello world”
^ ^
| ^
y -----------+ ^
> > >
It matters not that x and y's names may be spelled #name and ##current_name.
Here is another code example:
x = "hello"
y = x
y << " world"
puts x, y
--output:--
hello world
hello world
x.next!
puts x, y
--output:--
hello worle
hello worle
Here is an example with immutable types:
1. x = 10:
x ------> 10
2. y = x:
x ---------> 10
^
|
y -----------+
3. y += 1
=> y = y + 1
=> y = 10 + 1
And 10 + 1 creates the new Integer object 11 and assigns it to y:
x ------> 10
y ------> 11
The expression 10 + 1 does NOT increment the Integer object 10 that both x and y refer to--because Integer objects are immutable.
Here is another example:
x = 10
y = x
x.next
puts x,y #=> ??
x.next creates a new Integer object 11, and because the newly created Integer object 11 is not assigned to a variable, 11 is discarded, so x and y still refer to the same Integer object 10.

Array.map { |x| change value } is removing it from the array, why?

The objective is to move each letter to the next letter in the alphabet,
within the map, it successfully changed the letter but once i'm out of there the value disappears, except the vowels. How come?
def LetterChanges(str)
abc = [*("a".."z")]
result = str.split(//)
result.map! do |x|
if abc.include?(x)
if x == "z"
x = "A"
else
x = abc[abc.index(x)+1]
# if you puts x here, you can see it changes value correctly
if x == "a" || x == "e" || x == "i" || x == "o" || x == "u"
x.capitalize!
end
end
end
#However here, the changed values that are not vowels disappear
# WHY is that happening, is the second if (vowel) affecting it? How?
end
puts "#{result.join}" #<--- its only putting the vowels
return result.join
end
LetterChanges("what the hell is going on?")
The block passed to map! needs to return a value in all cases for this to work.
http://www.ruby-doc.org/core-2.2.0/Array.html#method-i-map-21
def LetterChanges(str)
abc = [*("a".."z")]
result = str.split(//)
result.map! do |x|
if abc.include?(x)
if x == "z"
x = "A"
else
x = abc[abc.index(x)+1]
if x == "a" || x == "e" || x == "i" || x == "o" || x == "u"
x.capitalize!
end
end
end
x
end
result.join
end
The problem is your if. When x is a not a vowel that return nil.
Just Change this line
if x == "a" || x == "e" || x == "i" || x == "o" || x == "u"
x.capitalize!
end
With this
x = %w{a e i o u}.include?(x) ? x.capitalize : x

How do I perform variable assignment with a loop, and break?

Here is the logic:
y = 'var to check for'
some_var = some_loop.each do |x|
x if x == y
break if x
end
Is there a better way to write this?
Something like
x && break if x == y
Thank you in advance!
The correct answer is to use include?. eg:
found = (array_expression).include? {|x| x == search_value}
It's possible to also use each and break out on the first matched value, but the C implementation of include? is faster than a ruby script with each.
Here is a test program, comparing the performance of invoking include? on a very large array vs. invoking each on the same array with the same argument.
#!/usr/bin/env ruby
#
require 'benchmark'
def f_include a, b
b if a.include?(b)
end
def f_each_break a, b
a.each {|x| return b if x == b }
nil
end
# gen large array of random numbers
a = (1..100000).map{|x| rand 1000000}
# now select 1000 random numbers in the set
nums = (1..1000).map{|x| a[rand a.size]}
# now, check the time for f1 vs. f2
r1 = r2 = nil
Benchmark.bm do |bm|
bm.report('incl') { r1 = nums.map {|n| f_include a,n} }
bm.report('each') { r2 = nums.map {|n| f_each_break a,n} }
end
if r1.size != r2.size || r1 != r2
puts "results differ"
puts "r1.size = #{r1.size}"
puts "r2.size = #{r2.size}"
exceptions = (0..r1.size).select {|x| x if r1[x] != r2[x]}.compact
puts "There were #{exceptions.size} exceptions"
else
puts "results ok"
end
exit
Here is the output from the test:
$ ./test-find.rb
user system total real
incl 5.150000 0.090000 5.240000 ( 7.410580)
each 7.400000 0.140000 7.540000 ( 9.269962)
results ok
Why not:
some_var = (some_loop.include? y ? y : nil)

Resources