views:

1508

answers:

9

One of the very tricky question asked in an interview...

we need to swap the values of two variables like a=10 and b=15

Generaly to swap two variables values, we need 3rd variable like..

temp=a
a=b
b=temp

Now the requirement is, swaping value of two variable values without using 3rd variable?

How can be accopmplish this?

+38  A: 

Using the xor swap algorithm

void xorSwap (int* x, int* y) {
    if (x != y) { //ensure that memory locations are different
       *x ^= *y;
       *y ^= *x;
       *x ^= *y;
    }
}


Why the test?

The test is to ensure that x and y have different memory locations (rather than different values). This is because (p xor p) = 0 and if both x and y share the same memory location, when one is set to 0, both are set to 0. When both *x and *y are 0, all other xor operations on *x and *y will equal 0 (as they are the same), which means that the function will set both *x and *y set to 0.

If they have the same values but not the same memory location, everything works as expected

*x = 0011
*y = 0011
//Note, x and y do not share an address. x != y

*x = *x xor *y  //*x = 0011 xor 0011
//So *x is 0000

*y = *x xor *y  //*y = 0000 xor 0011
//So *y is 0011

*x = *x xor *y  //*x = 0000 xor 0011
//So *x is 0011


Should this be used?

In general cases, no. The compiler will optimize away the temporary variable and given that swapping is a common procedure it should output the optimum machine code for your platform.

Take for example this quick test program written in C.

#include <stdlib.h>
#include <math.h>

#define USE_XOR 

void xorSwap(int* x, int *y){
    if ( x != y ){
        *x ^= *y;
        *y ^= *x;
        *x ^= *y;
    }
}

void tempSwap(int* x, int* y){
    int t;
    t = *y;
    *y = *x;
    *x = t;
}


int main(int argc, char* argv[]){
    int x = 4;
    int y = 5;
    int z = pow(2,28); 
    while ( z-- ){
#       ifdef USE_XOR
            xorSwap(&x,&y);
#       else
            tempSwap(&x, &y);
#       endif
    }
    return x + y;    
}

Compiled using:

gcc -Os main.c -o swap

The xor version takes

real    0m2.068s
user    0m2.048s
sys  0m0.000s

Where as the version with the temporary variable takes:

real    0m0.543s
user    0m0.540s
sys  0m0.000s
Yacoby
Might be worth explaining the why of the test (i.e. that the triple xor approach fails horribly if x and y reference the same object).
dmckee
look scary but +1 :)
PoweRoy
Thanks for all of you, All shared very good solution, So I am giving 1+ to all...
Muhammad Akhtar
I don't know how this got so many upvotes when the code is so broken. Both swaps in the tested code segment are completely incorrect. Look close.
SoapBox
Drew Hall
@SoapBox Good catch. Fixed and re-tested and I don't get any major difference in the timings.
Yacoby
The questioner said two variables, not ints. :P
Plumenator
+3  A: 

Have you looked at XOR swap algorithm?

MBO
Thanks for all of you, All shared very good solution, So I am giving 1+ to all...
Muhammad Akhtar
+19  A: 
a = a + b
b = a - b // b = a
a = a - b
Dor
Thanks for all of you, All shared very good solution, So I am giving 1+ to all...
Muhammad Akhtar
What if `a+b` overflows?
Alok
@Alok: That's not taken in considerations, thus it's impractical :)
Dor
If a and b are of the same, basic, sized integer types (like `int`, `unsigned short`, ...), it still works out in the end, even with overflow, because if a + b overflows, then a - b will underflow. With these basic integer types, the values just rollover.
Patrick Johnmeyer
In C, using this on `unsigned` integer types is OK and works always. On signed types, it would invoke undefined behaviour on overflow.
jpalecek
+8  A: 

As already noted by manu, XOR algorithm is a popular one which works for all integer values (that includes pointers then). For the sake of completeness I would like to mention another less powerful algorithm with addition/subtraction:

A = A + B
B = A - B
A = A - B

Here you have to be careful of overflows/underflows, but otherwise it works just as fine. You might even try this on floats/doubles in the case XOR isn't allowed on those.

Vilx-
Thanks for all of you, All shared very good solution, So I am giving 1+ to all...
Muhammad Akhtar
+21  A: 

the general form is:

A = A operation B
B = A inverse-operation B
A = A inverse-operation B 

however you have to potentially watch out for overflows and also not all operations have an inverse that is well defined for all values that the operation is defined. e.g. * and / work until A or B is 0

xor is particularly pleasing as it is defined for all ints and is its own inverse

jk
+1 for generality
int3
Thanks for all of you, All shared very good solution, So I am giving 1+ to all...
Muhammad Akhtar
+3  A: 

Stupid questions deserve appropriate answers:

void sw2ap(int& a, int& b) {
  register int temp = a; // !
  a = b;
  b = temp;
}

The only good use of the register keyword.

MSalters
Is an object declared with storage-class register not a "variable"? Also I'm not convinced this is a good use of register, since if your compiler can't optimise this already then what's the point of even trying, you should either accept whatever rubbish you get or write the assembly yourself ;-) But as you say, a dodgy question deserves a dodgy answer.
Steve Jessop
Pretty much all modern compilers ignore the register storage class, as they have a much better idea of what gets frequently accessed than you do.
ceo
Note that this answer is intended for interview(er)s, not compilers. It especially takes advantage of the fact that the kind of interviewers who ask this kind of question don't really understand C++. So, they cannot reject this answer. (and there is no Standard answer; ISO C++ talks about objects not variables).
MSalters
Ah, I get you. I was looking in the C standard for mention of variable as a noun, and not just meaning non-const. I found one in n1124, in the section on for loops defining the scope of "variables" declared in the initialiser. Then I realised the question was C++, and didn't bother searching to see if C++ had made the same typo anywhere.
Steve Jessop
+8  A: 

No-one has suggested using std::swap, yet.

std::swap(a, b);

I don't use and temporary variables and depending on the type of a and b the implementation may have a specalization that doesn't either. The implementation should be written knowing whether a 'trick' is appropriate or not. There's no point in trying to second guess.

More generally, I'd probably want to do something like this, as it would work for class types enabling ADL to find a better overload if possible.

using std::swap;
swap(a, b);

Of course, the interviewer's reaction to this answer might say a lot about the vacancy.

Charles Bailey
of course in C++0x swap will use rvalue references so will be even better!
jk
Everyone wants to show off the shiny xor or other trick they learned, with various caveats about how to use it, but this indubitably is the best answer.
Roger Pate
A: 

I believe it's safe to say that all of the above answers address the question quite well. One thing that hasn't been addressed here, probably due to political correctness, is the interviewers need for a basic English 101 class. Yes, taking into consideration that the interviewer may not have English as their first language. However, if they're interviewing in the U.S.A. they should command the language of their candidate. The point being, as the example illustrates, often they don't.

Example: "How can be accopmplish this?"

As Mr. Bailey & Null303 has addressed, other than making the unknowing candidate squint a bit as they hopefully write down one of the above solutions, hopefully this wouldn't be the deciding factor of whether the candidate gets the job or not. Then, in this day and age, there's reality.

Mr
Have you ever considered that it's the questioner who made the communication error?
GMan
+1  A: 

More trivia, there's also the InterlockedCompareExchange functions, not a portable solution however.

Chris O