hockmode hockmode - 1 month ago 9
Ruby Question

Ruby Variables Swap confusion

i'm trying to figure out why this swap does not work properly. I added

p
to check the values on repl.it This is a partition method for a quicksort:

def partition (array, from, to)
#declared pivot to last index of array
pivot = array[to]
pIndex = from
for i in from..to-1
if array[i] <= pivot
array[i], array[pIndex] = array[pIndex], array[i]
pIndex += 1
end
end
p pivot
p array[to]
### why doesn't this work properly? pivot is same as array[to]
### array[pIndex], pivot = pivot, array[pIndex]
### the swap below works
array[pIndex], array[to] = array[to], array[pIndex]
p array
return pIndex
end


I have a
pivot = array[to]
. It is then swapped with an array[pIndex]:
array[pIndex], pivot = pivot, array[pIndex]
and
array[pIndex]
value changes to
pivot
but
pivot
did not change to
array[pIndex]
. But when I do this instead:
array[pIndex], array[to] = array[to], array[pIndex]
it works perfectly find. Can anyone tell me why?

Example with an array:

arr = [7, 2, 1, 6, 8, 5, 3, 4]


partition(arr, 0,7)


Before the last swap happens the array is
[2, 1, 3, 6, 8, 5, 7, 4]
. My last line of swap is suppose to swap
pivot
which is 4, with
array[pIndex]
which is 6. This should change the array to
[2, 1, 3, 4, 8, 5, 7, 6]
.

Answer

Let's break down what parallel assignment is doing here.

Say we have an array:

arr = [1, 2]
arr[0], arr[1] = arr[1], arr[0]
# arr => [2, 1]

This is the expected behavior - we are simultaneously doing the following two operations:
arr[0] = arr[1] and arr[1] = arr[0].

Now suppose we do

arr = [1, 2]
first = arr[0]
first, arr[1] = arr[1], first
# arr => [1, 1]
# first => 2

This is because now we are doing first = arr[1] and arr[1] = first.
first is a variable set to the value found at arr[0], and changing this variable does NOT mutate the array.