

How to Swap two numbers without temp variable in Java - javinpaul
http://javarevisited.blogspot.com.br/2013/02/swap-two-numbers-without-third-temp-variable-java-program-example-tutorial.html

======
crntaylor
There are many ways to swap two variables without using a temp variable, as
long as the type of the variables is a mathematical group[0].

If the group operation is denoted <>, with identity e, and the inverse of 'a'
is 'inv(a)' then you would do

    
    
        a = a0;
        b = b0;            // initial assignment
    
        a = a <> b;        // a = a0 <> b0 and b = b0.
        b = a <> inv(b);   // a = a0 <> b0 and b = a0 <> b0 <> inv(b0) = a0.
        a = inv(b) <> a;   // a = inv(a0) <> a0 <> b0 = b0 and b = a0.
    

This works when a and b are ints, which are a group with the operator '+' and
identity '0', and inverses inv(n) = -n (see [1])

It works when a and b are _nonzero_ floats, which are a group under
multiplication with identity 1.0 and inverses inv(x) = 1/x (but see [2]).

It works when a and b have fixed-length binary representations, because fixed-
length binary strings are a group where the operation is xor (or '^') and
inv(x) = x.

It works when a and b are matrices of the same dimension, which form a group
in two different ways - under matrix addition, where the inverse is
elementwise negation, and under matrix multiplication (if a and b are
nonsingular) where the inverse is the regular matrix inverse [3].

Note that in my third line, the right-hand side of the assignment is inv(b) <>
a, whereas all the examples in the blog post used a <> inv(b). They were
implicitly assuming a commutative group (i.e. a <> b == b <> a for all a and
b) whereas my procedure works even for non-commutative groups, e.g. matrices
under matrix multiplication.

 _Edit_ : Obviously, if you actually use this in real code... WAT.

[0] <http://en.wikipedia.org/wiki/Group_(mathematics)>

[1] this even works if one of the operations causes an integer overflow - the
magic of modular arithmetic!

[2] floats don't really form a group, because of non-associativity of floating
point multiplication.

[3] <http://en.wikipedia.org/wiki/Invertible_matrix>

~~~
jheriko
Actually, isn't having unique inverses a weaker requirement than being a
group? Maybe I am wrong...

~~~
crntaylor
There are algebraic objects for which inverses are defined, but which aren't
groups: namely groupoids, quasigroups and loops.

In groupoids the binary operation isn't total, i.e. there can be pairs (a,b)
for which a <> b is not defined -- so we can't use groupoids.

In quasigroups and loops the binary operation doesn't need to be associative.
But we require associativity, so that we can deduce

    
    
        (a <> b) <> inv b == a <> (b <> inv b) == a <> e == a
    

So we do actually need all the properties of a group.

~~~
crntaylor
A commenter on Reddit pointed out that quasigroups require both left and right
division operators \ and /, and that even though they are not associative, the
axioms

    
    
        x \ (x * y) = y
        x * (x \ y) = y
        (x * y) / y = x
        (x / y) * y = x
    

must hold -- so in fact, quasigroups are good enough!

------
asgeirn
While these are neat for things like a programmer's interview question I would
be very careful about actually using these in real code, for two reasons:

1\. It obfuscates the code for very little benefit. Readability suffers more
than performance gains.

The JVM could employ similar tricks under the covers for performance reasons
if it detects that this is on the hot path.

2\. The code is sensitive to overflow, sign handling, Not-a-Number, and
divide-by-zero.

Both these points should be raised by an experienced programmer.

~~~
CJefferson
Actually, it's worse than that.

In both Java and C/C++, doing this kind of thing actually makes code slower.
It only makes sense in assembler.

When the compiler can deduce that two variables already in registers have
swapped value, it simply relabels the registers, making swap a 0-cost
operation. Obviously if are swapping two memory locations, you have to read,
but a temporary optimises to:

mem1 -> reg1 mem2 -> reg2 reg1 -> mem2 reg2 -> mem1

While a swap trick, if the compiler can't backward-enginner it out has to add
a bit of xoring (or adding).

gcc actually has an optimisation pass with the specific job of trying to take
out this trick. Unfortunately, it can't always work because if you try using
these tricks on two pointers to the same memory location, you end up zeroing
out the value rather than doing nothing (which a proper temporary would).

~~~
viraptor
To add one more evil edge case - if you're using something like libgc in your
project and try swapping pointers that way, there's a chance you're going to
lose your memory by accident.

------
mcherm
It's "cute", I'll give you that. But what possible use could this have? Using
a temp variable is MORE likely to be optimized by the compiler[1] and is FAR
easier for someone reading the code to understand. Using it in an interview
falls into the trap of asking useless and irrelevant questions that weed out
perfectly good candidates. All in all, it's a bad idea.

[1] - I don't actually know this... but I suspect that it's true.

~~~
city41
Not to mention this approach has issues with overflow.

~~~
sltkr
The first two methods don't.

~~~
city41
ah yep, you are correct.

------
ed_blackburn
If I wanted to find somebody who understood bitwise operations _maybe_ useful.

If I'm looking to find a developer who can write maintainable line of business
software, which Java is a common fit for then I'd be aghast if this was
proposed as a sensible, maintainable solution.

This trick just reminds me of a long list of things that people ask for at
interview, which has no demonstrable link to the job at hand. Why not ask for
someone to memorise a complex api? Or understand a workaround for a long
standing "won't fix" framework.

Pointless. Useless.

~~~
blablabla123
Seeing it since recently more often in Blogs, I see increased readability.
After all, you just need to remember 3x XOR (a-b-a).

I find the swap solution w/ temp solution to be more painful for my eyes. It's
also 3 lines, but less homogenous.

------
xmodem
Cool trick. If I ever see this in your real-world production code, you're
fired.

------
praptak
The really nasty edge case is aliasing. Say you're swapping a[i] with a[j].
What happens when i==j? Nope, not what any sane person expects a swap
operation to do in this case...

This nasty trick was actually used in one of the Underhanded C Contest entries
in 2007.

------
pgsandstrom
My solution ended up like this:

a = b + (b = a) - a;

~~~
dbush
In Java, it seems to work, but in C (gcc 4.6.3) it doesn't. a ends up
unchanged, since the first instance of b contains the original value of a when
evaluated. Not sure why Java evaluates it the way it does.

~~~
emn13
That's because java is much stricter about enforcing the order of evaluation
in these kinds of aliased statements, whereas in C it's undefined and the
compiler just "does something". Of course, you'd have to be a real code-
masochist to do this to yourself even in java...

------
justincormack
Sane programming languages have multiple assignment ie a, b = b, a or some
other syntax.

------
markb139
You guys need to read the book "hackers delight" full of really great stuff
like this ISBN-13: 978-0-321-84268-8 ISBN-10: 0-321-84268-5

------
iconjack
This is a very old trick. According to Knuth, it goes back to at least 1961,
where it was found in IBM programming course notes in a more general form that
includes a mask:

x ← x ⊕ y, y ← y ⊕ (x & m), x ← x ⊕ y

The mask determines the subset of bits that get swapped.

------
retube
Funny this should be on the front page the same day that there is stuff about
interview "puzzles"

1) This is not really a programming questing. It is a logic or math or
algorithm question.

2) Please tell me a real-world programming situation where this would be
required.

------
mailarchis
I guess the third approach breaks if one of the two numbers is 0

~~~
CJefferson
Or if an overflow occurs (while methods 1 and 2 work fine even with overflow,
in Java at least as overflow semantics are well defined).

------
jheriko
two things i'd want to add. firstly the arithmetic with +/- fails when
over/underflow occurs. secondly xor works because it is its own inverse. the
more generic answer is using any operator that forms a group over the
potential values to be swapped... as another comment explains

i remember feeling fantastically clever when i rediscovered this about 15
years ago. it has been of nearly zero value to me since.

~~~
imd
+/- doesn't fail in a language where + is addition modulo n.

~~~
jheriko
true, but lots of things work in special cases.

------
kombinatorics
Simple yet difficult to conjure. This is awesome!

~~~
dietrichepp
What makes it awesome? It seems like a way to take something simple (swapping
variables) and write it in a complex way (three operations) so that neither
the humans nor the compilers reading it will know what is going on.

Real temporary variables are clearer for both humans and machines.

~~~
imd
Read crntaylor's explanation of this via group theory:
<https://news.ycombinator.com/item?id=5278915>

So this is awesome insofar as you find things like group theory awesome (I
did). But like he says, if you find this awesome to use in production code,
that's a horse of another color.

------
tocomment
This would be a great question for rejecting an otherwise qualified job
candidate ...

~~~
southphillyman
Yea it's very simple but in an interview environment I probably would have
over thought this. (I guess that's the point though)

------
pbhjpbhj
My initial reaction to the question was simply assign the value of one
variable as the name of the other. Does that count?

    
    
        a = a0
        a0 = b0 // initial assignments
        a = b0
        a0 = a0 // swapped

