Remove value from Variable - ruby

This is probably a very trivial question, but..
Assuming we have a variable 'a' that has a value of 10
Then we have a variable 'b' that has a value of 5
Can I remove the value of 'b' from 'a' (leaving 5) and change the value of a each time?
In my head I think of it as:
a - b = 5
a - b = 0
a - b = -5
etc etc..
Thanks!

Consider this:
a = 10
b = 5
a = a - b
Now the value of a is 5. This is because Ruby evaluates what is on the right side of the assignment operator = first and then assigns that value to whatever is on the left side.
#Another way to put it
a = (a - b)
There is also a shortcut since this type of math is very common
a = a - b
a -= b
# These are both the same
If you want to do this a certain number of times, try a loop.
a = 10
b = 5
3.times do {a -= b}
# a is now -5
For further basic Ruby learning, I would suggest Try Ruby to get you started on concepts as I mentioned above. (Type "next" there to get started)

Related

count number of times a loop runs

I am new to programming I want to know how many times iteration takes place in the following function.I just want to how the number of iteration depends on a and b
where A and B are binary numbers .For example A=101010 and b=1011010.
The following is algorithm for adding two numbers without using + operator
while B is greater than 0:
U = A XOR B
V = A AND B
A = U
B = V * 2
I'm going to assume the usual convention that values that are non-zero are considered True and that 0 evaluates to False.
Since you didn't specify the initial value of A, let's consider both cases (I'm assuming that B==True at init otherwise there would be no iterations):
CASE 1: A==False => (U==True and V==False) => B=0 => iterations stop
CASE 2:A==True => (U==False and V==True) => B=True, A=False => this is now CASE 1
So, depending on the initial value of A and asuming B==True at the start, there will be either 1 or 2 iterations.

Different results when using regular variable assignment and mass variable assignment

Translated a function that uses mass variable assignment to a function that uses regular variable assignment
# mass assignment
def fibo_finder n
a, b = 0, 1
n.times { a, b = b, a + b }
a
end
# regular assignment
def fibo_finder2 n
a = 0
b = 1
n.times do
a = b
b = a + b
end
return a
end
puts "Must be: 3. fibo_finder: #{fibo_finder(4)} fibo_finder2: #{fibo_finder2(4)}"
puts "Must be: 13. fibo_finder: #{fibo_finder(7)} fibo_finder2: #{fibo_finder2(7)}"
puts "Must be: 55. fibo_finder: #{fibo_finder(10)} fibo_finder2: #{fibo_finder2(10)}"
Running the code results to:
Must be: 3. fibo_finder: 3 fibo_finder2: 8
Must be: 13. fibo_finder: 13 fibo_finder2: 64
Must be: 55. fibo_finder: 55 fibo_finder2: 512
At first glance, the two functions look equivalent aside from how the variables were assigned. But the results show otherwise.
Is Ruby doing something special when variables are assigned using mass assignment?
I'm using repl to run the code
Yes.
In your mass assignment example:
a, b = b, a + b
the assignments are carried out in parallel - both right-hand expressions are evaluated and then the two results are assigned to the left hand side.
In your second example:
a = b
b = a + b
a is set to b and then b is set to a + b (or, b + b because a is now equal to b)
The two assignments are not equivalent.
In the parallel assignment:
a, b = b, a + b
The right hand side are evaluated, collected an an array, and then the left hand side gets the value from this array. It's equivalent to:
arr = [b, a + b]
a, b = arr
Note that in b gets the value of a + b with the original value of a.
Suppose:
a = 1
b = 2
Then with parallel assignment,
a,b = b,a #=> [2, 1]
a #=> 2
b #=> 1
By contrast:
a = 1
b = 2
a = b #=> 2
b = a #=> 2
a #=> 2
b #=> 2
Parallel assignment is often used for swapping values of variables, to avoid the need to create a temporary variable. If it worked as in my second example you couldn't use it for that.

Using for-loop to add numbers together

If I randomly put in two numbers (first number is smaller), how do I use a for-loop to add all the numbers between and itself?
ex:
first number: 3
second number: 5
the computer should give an answer of '12'.
How do I do that using a for-loop?
In Ruby we seldom use a for loop because it leaves litter behind. Instead, you can very simply do what you want using inject:
(3..5).inject(:+) # => 12
This is using some of the deeper Ruby magic (:+), which is a symbol for the + method and is passed into inject. How it works is a different question and is something you'll need to learn later.
Don't insist on doing something in a language using a particular construct you learned in another language. That will often force non-idiomatic code and will keep you from learning how to do it as other programmers in that language would do it. That creates maintenance issues and makes you less desirable in the workplace.
Simple for loop across the range you defined:
puts "Enter first number: "
first = gets.to_i
puts "Enter second number: "
second = gets.to_i
total = 0
for i in (first..second) do
total += i
end
puts total
Note that if you don't enter a valid number, it will converted to 0. Also this assumes the second number is larger than the first.
In Rails, or in plain-vanilla Ruby with ActiveSupport, you can do something even simpler than a for loop, or than what other people wrote.
(first_num..second_num).sum
This is shorthand for sum in Ruby:
sum = 0
(first_num..second_num).each { |num| sum += num }
first, second = [3,5]
for x in (0..0) do
p (first + second)*(second - first + 1) / 2
end
I know you said for loop, but why not use what Ruby gives you?
> a = 3
> b = 5
> a.upto(b).inject(0) {|m,o| m += o}
=> 12
If you insist on a for loop...
> m = 0
=> 0
> for i in 3..5
* m += i
* end
=> 3..5
> m
=> 12
Since Ruby 2.4 you directly call sum on an Enumerable.
For Example [1, 2, 3].sum #=> 6
In Ruby it's very rare to see a for loop. In this instance a more idiomatic method would be upto:
x = 3
y = 5
total = 0
x.upto(y) do |n|
total += n
end
puts total
# => 12
Another method would be to use reduce:
total = x.upto(y).reduce do |sum, n|
sum += n
end
...which can be shortened to this:
total = x.upto(y).reduce(&:+)

Ruby condition to increment one variable or the other

Lets say I have to variables in Ruby for a little game
times_won # Any integer
times_lost # Any integer
and the result of the last round
result # string, can be: "won", "lost" or "drawn"
What would be a nicer way of doing this
times_won += 1 if result == "won"
times_lost += 1 if result == "lost"
I'm trying with ternary operator but I dont know how to use it with multiple variables. Also a case statement isn't much nicer.
Maybe anyone knows a one-liner to blow my mind.
EDIT:
Where is the Error in a nested ternary operator like this?
times_won,times_lost += result == 'drawn' ? [0,0] : result =='won' ? [1,0] : [0,1]
You could use a hash:
#counter = {won: 0, lost: 0, drawn: 0}
result = :won
#counter[result] += 1
#counter
#=> {:won=>1, :lost=>0, :drawn=>0}
I've used symbols as keys, but it also works with string.
If other parts of your code rely on times_won and times_lost, you could implement them as methods:
def times_won
#counter[:won]
end
Regarding your edit
Mixing abbreviated assignment and multiple assignment doesn't work:
a, b += 1, 2 #=> SyntaxError
You have to specify the calculation explicitly:
a, b = a + 1, b + 2 # increments `a` by 1 and `b` by 2
And of course you can replace the fixed values with a more complex expression:
a, b = a + (result == 'won' ? 1 : 0), b + (result == 'lost' ? 1 : 0)

Why parentheses change returning value?

I'm learning ruby and I got stuck with probable simple problem. There is the code:
str = 'abc'
a = 1
b = 2
a = str.reverse if str.size > 3
b = (str.reverse if str.size > 3)
p a
p b
Output:
1
nil
Can somebody tell me what these parentheses change in return value ? Is it kind of "block" of code ?
They are two different statements.
The first one is a conditional assignment:
a = str.reverse if str.size > 3
The if applies to the whole line. If str.size is not greater than 3, then absolutely nothing happens; a is not touched at all. You could also write it this way:
if str.size > 3 then
a = str.reverse
end
Being able to stick the if on the end just lets you do it in one line instead of a block.
The second one is an assignment of a conditional value.
b = (str.reverse if str.size > 3)
The value of b will always be changed in this case, no matter what; the value of str.size just determines what it is changed to. You could also use the block-form of if here:
b = if str.size > 3 then
str.reverse
end
The important difference is that the assignment to b happens outside the if, so it's not conditional; it always happens.
Parentheses don't create blocks, but they do determine precedence. Whenever you have a statement that could be interpreted multiple ways depending on the order in which things happen, what actually happens is determined by precedence rules. For instance, standard arithmetic rules tell us that this is true:
3 + 2 × 4 = 11
The answer isn't 20 because multiplication has precedence over addition. Parentheses let you change that; the above is equivalent to
3 + (2 × 4) = 11
and if you want the answer to be 20, then you could write this instead:
(3 + 2) × 4 = 20
Same thing goes for Ruby. Without parentheses, the first line is equivalent to this parenthesized version:
(a = str.reverse) if str.size > 3
which makes it clear that the assignment is what is guarded by the condition, not just the value being assigned.
Parentheses will change priority during operation.
Code between parenthesis will be evaluated as boolean due to its status as conditional expression.
Like #Mark Reed said, there are differents statements. And it is up to your intention to use the correct one. Hope it helped. ;)

Resources