views:

3144

answers:

19

How many different ways can you come up with to swap the values of two variables without using any third variable ?

I use this one:

     a^=b^=a^=b
+11  A: 

In Ruby:

a,b = b,a
Pesto
I think you'd have to use assembly to get any more elegant.
Adam Lassek
Works in Python too.
Bastien Léonard
+1  A: 

Read this in my first book on C (Programming with C -- Sudhir Kaicker):

a += b;
b = a - b;
a = a - b;
Vulcan Eager
assumes the types support the += operator
Adam Naylor
I typed those on a line each. Why are they appearing in one line?
Vulcan Eager
@agnel - you need to mark the lines as "code"
ChrisF
Assuming a += b doesn't overflow the type...
Good call, null, although it's still guaranteed to work on unsigned integral types.
David Thornley
@ChrisF - Thanks. I also had to type in some leading text to make it work.
Vulcan Eager
Worse, for floating point numbers, this may cost you precision due to subtractive cancellation. For fixed point numbers, this may result in overflows. It is a very POOR way to solve the problem.
woodchips
If 'the problem' is that you only have two variables available, there might be other problems that need attention as well ;)
Andy Mikula
@woodchips: you'd never want to do this for floating point numbers as you point out. For fixed point numbers you don't have to worry about overflow, it does the right thing as long as your system supports wraparound integer math: the only case I've ever seen that doesn't is MATLAB's "fixed point" toolbox which for some weird reason is different and saturates at 0 and the max integer value.
Jason S
+2  A: 
a = a + b
b = a - b
a = a - b

There are many ways to do this. Trivially replacing +- with */ will also do it.

sykora
If a and b are floating-point numbers, * / probably wouldn't do it.
Michael Myers
Actually, if a == 0 or b == 0, then it your */ substitution will lead to dividing by zero.
FarmBoy
Also, the semantics of integer division means that, for most values of a and b, * / will not work properly.
Matt J
Don't forget that floating-point arithmetic is inexact. You're unlikely to wind up with the correct results there. It should work with integers, barring overflow, since you're dividing a number by its factors, which does work in integer division.
David Thornley
This works in any abelian group. Change the last assignment to a = (-b) + a and it will work also for nonabelian groups. It works with * if * is a group operator (for integers and floats, it's not).
fredrikj
Subtractive cancellation will cause problems here. For fixed point numbers, overflows are a risk too. Avoid this style.
woodchips
+15  A: 

Generalising your example slightly, whenever two binary operations # and @ are inverses of each other, the following sequence will exchange the values of a and b:

a = a # b
b = a @ b
a = a @ b

Your example works because ^ (XOR) is its own inverse.

This is a neat trick. Unfortunately, some people think it makes a good interview question.

[EDIT: Thanks to mouviciel for correcting an error on the 2nd line.]

j_random_hacker
Yes, You are absolutely correct saying this. Secondly, I've observed that the order of operation also matters. You can get proper swaping results not only by just executing in the order you've mentioned but also by exeuting them in reverse order as well.
this. __curious_geek
Isn't it b = a @ b on the second line?
mouviciel
Yep - I hate this sort of interview question, because all it shows is how clever the interviewer thinks he is
ChrisF
@mouviciel: Good spotting! Fixed.
j_random_hacker
@ChrisF: Sometimes the approach of solving a Problem matters much more than actual solution. The interviewer basically inteds to examine how you are approaching to the Problem !!!
this. __curious_geek
@s_ruchit: Not quite: if # is + and @ is -, reversing the order of the 3 assignments doesn't work.
j_random_hacker
@ChrisF: I totally agree. It isn't useful in real life, it's far from obvious unless you've seen it before, and it's easily remembered by people who have seen it before, and who are rubbish at programming.
j_random_hacker
xor has another desirable property: it doesn't overflow (unlike + and -)
Roberto Bonvallet
@Roberto: In nearly all languages and implementations, integer + and - will use 2's complement arithmetic, meaning that overflows are "symmetrical": even if z = (x + y) overflows, (z - y) == x. (And the same is true with + and - swapped.)
j_random_hacker
+1  A: 

temp = a ; a = b ; b = temp ;

'Clever' ways are just noise, IMO.

Write code for people first, computers 2nd.

Visage
I assume this question was asked with more of a 'Hey, check out this neat trick' attitude as opposed to a 'This is how people should write their code' attitude.I agree with you, though.
tehblanx
@tehblanx: I seriously wish to learn another possible way to achieve this. Sometimes the approach of solving the problem matters much more than the solution actually.
this. __curious_geek
+10  A: 

PHP

list($a, $b) = array($b, $a);

JavaScript 1.7

[a, b] = [b, a]

Python

a, b = b, a
Ionuț G. Stan
I don't think solutions like this really address the question - this is an interview "gotcha" where they're looking for the xor trick, and my sense is that these examples are just the language nicely hiding the swap. Even though you're not explicitly creating the swap, it's not what they're asking.
Steve B.
I haven't seen the word interview in the question. Anyway, while these solutions don't use the XOR trick they may prove some imagination in an interview. I haven't seen the PHP trick anywhere else.
Ionuț G. Stan
Shockingly, that Javascript solution doesn't work in IE. It is legal Javascript though and works in all modern browsers. :)
SamGoody
A: 

In F#

let swap  (a,b) = (b,a);;
Conrad
+5  A: 

The XOR swap is a terrible, terrible thing.

e.James
Why is it terrible?
jeffamaphone
It's useless in high-level languages. In ASM it may be useful for optimizing.
Bastien Léonard
It's a neat "trick". Nothing more. Given that any decent compiler would keep the temporary variable in a register, the straightforward way is almost definitely more efficient and easily more readable and understandable.
Michael
It only works with unsigned integers, and it breaks all kinds of good design concepts. It even fails as an optimization, since most processors can perform the swap in a single SWAP instruction.
e.James
@Bastien: In x86 assembly language, the dedicated XCHG instruction is likely to be faster.
j_random_hacker
@eJames: Yes it's terrible, but the XOR swap will in fact work on signed integers too.
j_random_hacker
@j_random_hacker: Yes, that makes sense. Thank you for the correction.
e.James
For high-level languages on fast computers it's next-to-useless. For small embedded systems with resource limitations it may be important. (although if you're in a situation where you can't find enough memory for a temporary RAM variable, you've got other problems)
Jason S
A: 

I asked this question awhile back:

How does XOR variable swapping work?

It got some really good responses if you are curious how this is possible.

Simucal
A: 

My Forth is way rusty, but:

. A
. B
@ A
@ B

(Does "@" write the top of the stack to a variable, or am I rustier than I thought? Anyway, this should work for all stack-based languages.)

If you're using the standard Forth idiom of treating stack entries as temporary variables, there's always:

SWAP
David Thornley
A: 

In Common Lisp:

(psetf a b b a)
Svante
I saw it in the mirror...
Svante
The actual implementation of psetf relies on temporary variables.
Eduardo León
No, that is implementation dependent. I could imagine that an optimized compiler can translate this to a single-cycle SWAP operation on whatever machine it runs on.
Svante
A: 
  1. Don't post any answers for interpreted languages. The interpreters are themselves whole programs with lots of variables. So, while there are no variables in your program, there are lots of variables in the program that runs your program.

EDIT: I didn't mean to offend the sensibility of those of you who use dynamic languages. They are very useful tools, but, to me, the definition of a variable is something that is in the call stack and isn't the address in memory of the instruction the program must return to after the current subroutine finishes. And those nice library functions and thingies you're used to have tons of temporary results. Those temporary results must be stored somewhere in the memory, whether you like to call it a variable or not.

  1. The XOR swap is a very good one. I like it.

EDIT: The optimal implementation of the XOR swap doesn't involve any temporary results that don't have to be stored in temporary variables (not even in machine code!). This is what I meant. Using the XCHG instruction is a nice alternative.


Eduardo León
By that argument, anything that's not assembler doesn't count.
Svante
To distinguish compiled languages from interpreted ones on that basis is silly.
woodchips
The swap in an interpreted language is often a language construct. You can think of it like a library function. There must be a call stack, where many temporary variables are allocated. Instead, in a C or ASM program that uses the XOR swap or the XCHG instruction, respectively, you can ensure there aren't any temporary variables in the stack.
Eduardo León
+1  A: 

Intel Assembly

Assuming the variables a, b are defined in .data:

mov  eax, a
xchg b, eax
mov  a, eax
Adam Lassek
Shouldn't you have brackets around `a` and `b` since they're memory references?
bcat
A: 

In Lua:

a,b = b,a

You have to like it. It goes for any number of vars.

You didn't mention in what language tho :P

majkinetor
No Constraint on Language but I'd prefer to have mathematical solution. The question has been tagged under 'math' Tag.
this. __curious_geek
A: 

In MATLAB:

[a,b] = deal(b,a);
woodchips
A: 

In assembly language of 8051 family , suppose X= 50 Y= 30

mov r1,#50 // r1=50 i.e. x

mov r0,#30 // r0=30 i.e. y

mov r2,r1 // r2=50, r1=50, r0=30

mov r1,r0 // r1=30, r0=30, r2=50

mov r0,r2 // r0=50, r1=30, r2=50

Hence initially X=r1=50 and Y=r0=30

after the sequence X=r1=30 and Y=r0=50

Note :- r0, r1 and r2 are registers of the 8051 microcontroller

Dharavk
read the question carefully. You cannot use 3rd variable or storage. you must do it with r0 and r1 only. You cannot use r2
this. __curious_geek
A: 

Works in many languages

Works only with numbers

a = a + b - (b = a);
presario
specifically, integers. It is also based on the side effect that (b=a) sets b to a and returns a.
nlucaroni
A: 

This is a simple method, logic can be implemented all the languages... Happy Sensible Coding..

$v = 'sriram';
$u = 'lakshmi';

$v .= $u;
$u = substr($v,0,(strlen($v) - strlen($u)));
$v = substr($v,(strlen($v) - strlen($u)-1), strlen($v));

echo 'u = ' . $u .'<br>';
echo 'v = ' . $v;
Sriram
To make it more sensible you should post a more 'general' method for swaping integers and floating-point numbers. Happy coding.
this. __curious_geek
A: 
#include <iostream>
using namespace std();
void main()
{
    int a=59;
    int b=67;
    a=a+b;
    b=a-b;
    a=a-b;
    cout<<"a="<<a<<"b="<<b<<endl;
}
Shahbaz Masud