Saturday, September 19, 2015

Swapping two variables without using a third, 1) generically and 2) Pythonically

By Vasudev Ram

One of the techniques taught in some beginners' programming courses, is how to swap the values of two variables, without using a third variable. It is sometimes given as an exercise to students. I remember it from an early course that I took.

[ If you don't know the solution, try it before reading on. Hint: Try it for two integers. No restrictions, other than not being allowed to use a third variable. ]
.
.
.
.
.
One solution to it, at least when the two variables contain integer values, is like this:

```>>> a, b = 1, 2
>>> print a, b
1 2
>>> a = a + b
>>> a, b
(3, 2)
>>> b = a - b
>>> a, b
(3, 1)
>>> a = a - b
>>> print a, b
2 1
```
Of course, the above method will only work for numbers, i.e. at least, for integers; it might or not work for all pairs a and b when a and b are floating-point numbers. Why? (*)

Similarly, it will not work when a and b are strings or any other data type.

(*) One reason it may not work for all floats (only some - I need to check this), is because some float values cannot be represented exactly in a computer that uses binary representation of numbers.

So that was the generic way, above (to swap the values of two integer variables, without using a third temporary variable), which will work in most or all programming languages.

Python has another, Pythonic way (though it also works in some other languages, I guess). It's just:

a, b = b, a

which does a parallel assignment of a and b's old values to each other, without overwriting either.

Interestingly, this 2nd way, since it does not involve addition and subtraction (as in a + b and a - b), is more general. For example, we can swap the values of two function objects:
```>>> def foo(): print "this is function foo"
...
>>> def bar(): print "this is function bar"
...
>>> foo()
this is function foo
>>>
>>> bar()
this is function bar
>>>
>>> foo
<function foo at 0x00000000029F09E8>
>>> bar
<function bar at 0x00000000029F0518>
>>>
>>> foo, bar = bar, foo
>>>
>>> foo()
this is function bar
>>> bar()
this is function foo
>>> foo
<function bar at 0x00000000029F0518>
>>> bar
<function foo at 0x00000000029F09E8>
```
Note that both calling the function, like foo(), and just entering its name at the Python shell, like foo, tell us that the name foo now refers to the original bar function object. And similarly the name bar now refers to the original foo function object.

And finally, to show what happens in the above function object swap, in a different way:
```>>> id(foo), id(bar)
(43977192L, 43975960L)
>>> foo, bar = bar, foo
>>>
>>> id(foo), id(bar)
(43975960L, 43977192L)
```
After writing this post, I googled for "swapping two variables without using temp" and found an interesting hit:

Swap Two Variables Without Using a Temp Variable (With Math!)

which throws more light on this subject, showing other ways to do it, and also goes into the mathematical theory behind it (involving groups - the mathematical kind) - which I remember as a fun math topic from college, with many applications in the real world. I even got to know about quasigroups from that post ... whew!

Referring to the swapping of function objects above, coincidentally, just recently I came across a post by Ned Batchelder on a very related topic: names and values in Python. The exact meaning of (identifier) names and values in Python is not as obvious as it may seem at first, and is also somewhat different from the way these things work in other languages like C or Java. It has to do with concepts like binding names to values (and also unbinding and rebinding them). Here is his post, which he also presented as a video at PyCon 2015:

Python Names and Values

There is a link to the video in his post, and it is also embedded below:

Dancing Bison Enterprises

Vasudev Ram said...

> groups - the mathematical kind) - which I remember as a fun math topic from college

Also rings and fields, which are other mathematical entities related to groups. And fun too.

From the Wikipedia article about mathematical groups:

"The ubiquity of groups in numerous areas within and outside mathematics makes them a central organizing principle of contemporary mathematics."

Just scanned the article and saw that groups have applications and physics and chemistry too.

Vasudev Ram said...

>saw that groups have applications and physics and chemistry too.

Typo; should be:

saw that groups have applications in physics and chemistry too.