Can someone explain this behavior:
a = b = c = 1, 2, 3
a # => [1, 2, 3]
b # => 1
c # => 1
In the assignment a = b = c = 1, 2, 3, the variables a, b, and c should be assigned [1, 2, 3]. Any idea?
Can someone explain why is this happening
#shivam already answered the question, but adding some parentheses might clarify things even more.
a = b = c = 1, 2, 3
is interpreted as:
a = [(b = (c = 1)), 2, 3]
The expression is evaluated in this order:
c = 1
b = ( )
a = [( ), 2, 3]
the variables a, b, and c should be assigned [1, 2, 3]
To get the expected result, you could write:
a = b = c = [1, 2, 3]
which is interpreted as:
a = (b = (c = [1, 2, 3]))
and evaluated in this order:
c = [1, 2, 3]
b = ( )
a = ( )
You are being confused
a=b=c=1,2,3
is actually:
a = (b = c = 1), 2, 3
that leaves
c = 1 # => 1
b = c # => 1
a = 1,2,3 # => [1, 2, 3]
To do what you are talking about you should do as follow:
a,b,c = 1,2,3
p a #=> 1
p b #=> 2
p c #=> 3
Related
This is the original link for the problem in hackerrank: https://www.hackerrank.com/challenges/the-birthday-bar/problem
I have been fighting with this problem in Ruby and I don't know why my counter always returns 1. This is the solution. I hope you can help me to understand what I'm making wrong.
s = [1, 2, 1, 3, 2]
d = 3
m = 2
def birthday(s, d, m)
array = []
cont = 0
sum = 0
m.times {array.push(s.shift)}
(m-1).times do
array.each {|i| sum = sum + i}
if sum == d
cont += 1
end
array.shift
array.push(s.shift)
end
return cont
end
birthday(s, d, m)
Though the following does not answer your question directly, it is a Ruby-like way of solving the problem, especially by making use of the methods Enumerable#each_cons and Enumerable#count.
def birthday(s, d, m)
s.each_cons(m).count { |a| a.sum == d }
end
s = [1, 2, 1, 3, 2]
d = 3
m = 2
birthday(s, d, m)
#=> 2 ([1, 2] and [2, ])
s = [2, 2, 1, 3, 2]
d = 4
m = 2
birthday(s, d, m)
#=> 2 ([2, 2] and [1, 3])
s = [2, 4, 3, 2, 1, 2, 6, 1]
d = 9
m = 3
birthday(s, d, m)
#=> 4 ([2, 4, 3], [4, 3, 2], [1, 2, 6] and [2, 6, 1])
Notice from the doc that when each_cons is used without a block it returns an enumerator:
s = [1, 2, 1, 3, 2]
d = 3
m = 2
enum = s.each_cons(m)
#=> #<Enumerator: [1, 2, 1, 3, 2]:each_cons(2)>
enum will generate elements and pass them to count until there are no more to generate, at which time it raises a StopIteration exception:
enum.next #=> [1, 2]
enum.next #=> [2, 1]
enum.next #=> [1, 3]
enum.next #=> [3, 2]
enum.next #=> StopIteration (iteration reached an end) <exception>
We can write1:
enum.count { |a| a.sum == d }
#=> 2
After enum generates the first value ([1, 2]) the block variable a is assigned its value:
a = enum.next
#=> [1, 2]
and the block calculation is performed. As
a.sum == d
#=> [1, 2].sum == 3 => true
the count is incremented (from zero) by one. enum then passes each of its remaining values to count and the process is repeated. When, for example, [1, 3].sum == 3 => false is executed, the count is not incremented.
1. Note that since I just stepped through all the elements of enum, enum.next would generate another StopIteration exception. To execute enum.count { |a| a.sum == d } I therefore must first redefine the enumerator (enum = s.each_cons(m)) or Enumerator#rewind it: enum.rewind.
I would appreciate if someone could explain why the output of this code:
*a, b = [1, 2, 3, 4]
a[b-2] + b
is 7. Could anyone please break it down line by line so I understand what's going on here? How does this become 7?
To break anything down line by line one could use REPL:
*a, b = [1, 2, 3, 4]
#⇒ [1, 2, 3, 4]
a
#⇒ [1, 2, 3]
b
#⇒ 4
Using splat operator, we have decomposed the original array to new array and the single value. Now everything is crystal clear: a[b-2] which is a[2], which is in turn 3 (check a array.) and b is still 4.
3 + 4
#⇒ 7
when you assign array like this,
*a, b = [1, 2, 3, 4]
then it will assign
a = [1,2,3]
and b = 4
Now when you tried to print a[b-2] + b
a[b - 2] = 3
b = 4
3 + 4 = 7
for more understanding use rails console and run line by line.
*a, b = [1, 2, 3, 4]
a
=> [1, 2, 3]
b
=> 4
a[b-2] // b-2 = 2 find value at index of 2 in a, like a[2] is 3
=> 3
a[b-2]+b
=> 7
*a, b = [1, 2, 3, 4] it means a = [1,2,3] and b = 4 when you do a[b-2] + b it will be
+-----------------------+
a[b-2] + b | a[2] |
a[4-2] + 4 | | |
a[2] + 4 | a[1, 2, 3] |
3 + 4 | 0 1 2 -> index |
= 7 +-----------------------+
By using the splat operator on a we are basically letting a to scoop up all the other numbers that b does not need. So b takes one number from the array and a takes everything that is left.
b = 4
a = [1,2,3]
Now when we do this:
a[b-2] + b
It translates into:
a[4-2] + 4
a[2] + 4
Now we check what number is in position 2 in array a.
3 + 4 = 7
Just saw something like this in some Ruby code:
def getis;gets.split.map(&:to_i);end
k,=getis # What is this line doing?
di=Array::new(k){Array::new(k)}
It assigns the array's first element using Ruby's multiple assignment:
a, = [1, 2, 3]
a #=> 1
Or:
a, b = [1, 2, 3]
a #=> 1
b #=> 2
You can use * to fetch the remaining elements:
a, *b = [1, 2, 3]
a #=> 1
b #=> [2, 3]
Or:
*a, b = [1, 2, 3]
a #=> [1, 2]
b #=> 3
It works like this. If lhs has single element and rhs has multiple values then lhs gets assigned an array of values, like this.
a = 1,2,3 #=> a = [1,2,3]
Whereas if lhs has more elements than rhs, then excess elements in lhs are discarded
a,b,c = 1,2 #=> a = 1, b = 2, c = nil
Therefore
a, = 1,2,3 #=> a = 1. The rest i.e. [2,3] are discarded
In ruby its possible to combine multiple assignment with the splat operator in order to simulate first and rest (or head and tail) found in functional languages.
first, *rest = [1,2,3,4]
first # output: 1
rest # output: [2,3,4]
How is the splat operator achieving this?
You can have at most one splat operator in multiple assignment, and the splat operator will adjust the length of the array to exhaustively match what is on the right side. In other words:
1) When the number of variables on the left side is more than the length of the array on the right side, then, the variable with the splat will be assigned an empty array:
*a = []
# => a == []
*a, b = [1]
# => a == [], b == 1
a, *b = [1]
# => a == 1, b == []
*a, b, c = [1, 2]
# => a == [], b == 1, c == 2
a, *b, c = [1, 2]
# => a == 1, b == [], c == 2
a, b, *c = [1, 2]
# => a == 1, b == 2, c == []
...
2) Otherwise, the variable with the splat will expand to be filled up with the rest of the elements from the right side:
*a = [1, 2]
# => a == [1, 2]
*a, b = [1, 2, 3]
# => a == [1, 2], b == 3
a, *b = [1, 2, 3]
# => a == 1, b == [2, 3]
*a, b, c = [1, 2, 3, 4]
# => a == [1, 2], b == 3, c == 4
a, *b, c = [1, 2, 3, 4]
# => a == 1, b == [2, 3], c == 4
a, b, *c = [1, 2, 3, 4]
# => a == 1, b == 2, c == [3, 4]
....
I do this:
a = [1,2,3,4]
b = [2,3,4,5]
c = b - a
put c
I get this
answer -> [1]
I want this answer -> [1,1,1,1] (like matrix addition/subtraction)
I tried this:
c.each {|e| c[e] = b[e] - a[e]}
but I get this answer: [1,0,0,0]
Can someone give me a correct way to do this? Thanks a lot!
You could use zip:
a.zip(b).map { |x, y| y - x }
# => [1, 1, 1, 1]
There is also a Matrix class:
require "matrix"
a = Matrix[[1, 2, 3, 4]]
b = Matrix[[2, 3, 4, 5]]
c = b - a
# => Matrix[[1, 1, 1, 1]]
You can use each_with_index and map.
c = b.each_with_index.map { |n,i| n - a[i] }
# => [1, 1, 1, 1]