views:

221

answers:

8

Hi, all! Could someone please help me to solve such a task. I need to swap variable values without using any assignment signs. I tried to do it with a while loop but I coudn't store counter value anywhere. Thank you all in advance.

+2  A: 

See Bit Twiddling Hacks it'll show you how to do it in a number of different ways without using assignments.

Dave
These show ways to swap values without using a temporary variable, not without using assignment (unless you consider `op=` not to be an assignment).
LarsH
+2  A: 

Does xor-swap count?

     x ^= y;
     y ^= x;
     x ^= y;
Jakob
I notice 3 assignments in this code.
Ani
@Ani: That's why I asked :) The whole issue boils down to what you consider as an assignment. Konrads answer is an even better illustration of that since whether or not ++/-- are assignments is even more fuzzy.
Jakob
+1  A: 
int i = 10, j = 20;
i = i + j;
j = i - j;
i = i - j;
Khaniya
@Khaniya: I think most people think of '=' as an assignment sign.
High Performance Mark
@High Performance You made my day :D
Helper Method
+6  A: 

Since integers are immutable in C#, you cannot "Swap Integer variables without using any assignment"; you will need to reassign them somewhere, somehow. Perhaps you mean Swap two variables without using a temp variable? Or, if you meant without explictly using =, @Konrad Rudolph's answer is the way to go.

Ani
+6  A: 

Xor-swap uses assignments. But perhaps you’re allowed to use increment and decrement (which, strictly speaking, resolve to += 1 and -= 1 in C# but logically they are often considered to be different).

int tmp = 0; // C# complains if we don’t initialize!
while (a-- > 0)
    tmp++;
while (b-- > 0)
    a++;
while (tmp-- > 0)
    b++;

This is a logic sometimes used in the analysis of primitive calculi, such as the LOOP program formalism. Of course, these formalisms don’t require initialization of fields, otherwise the whole “no assignment” rule would be completely moot. In a strict calculus, tmp would have to be zero-initialized by a loop, too:

while (tmp > 0)
   tmp--;

This will work no matter what value tmp had before (provided tmp > 0, which is usually a requirement in all these calculi: negative numbers don’t exist).

But, to stress this once again, C# requires us to initialize each local variable (non-local variables are default-initialized) so this loop would be redundant in C#, and an initialization is still required.

As @Doc Brown pointed out in the comments, this only works for (positive!) integers – although theoretically (once again: not in C#!) this could be made to work with any type that can be represented on a Von Neumann architecture since they all reside in memory as numbers (to some base).

Konrad Rudolph
Souldn't you initialize `tmp` to `0`?
Kobi
Kobi is right. Since that would violate the 'rules', I guess you could make it a field?
Ani
@Kobi, @Ani: You’re right. C# requires initialization, I forgot. See the updated text. I think this is as close as we can get (with local variables).
Konrad Rudolph
This is C#, not C. tmp will be 0 without the initialization.
Jakob
@Jakob - please test that `:)`
Kobi
@Konrad: you should add a remark that this does only work for integers.
Doc Brown
@Kobi: That actually came as a surprise. How can I not have noticed that before?! :)
Jakob
works only for positive number's?
st0le
@st0le: Dang! Thanks for the catch.
Konrad Rudolph
A: 

I don't think this is even possible in C#.

The XOR answer is the standard, but you can only grab hold of the memory and manipulate its values directly in lower-level languages.

.net languages will allow you to perform the equivalent of an XOR operation and return the value but to store it you still have to assign it, as far as I'm aware. You just don't have the direct memory access to perform the operation in this manner, as far as I can think...

Frosty840
+6  A: 

You can use Interlocked.Exchange.

0xA3
So, the answer to this question is buried deep within the .net framework...
Kobi
Could someone show how ? why doesn't this works : Interlocked.Exchange(ref b, Interlocked.Exchange(ref a, b));
hoang
So shifting the problem to a library routine whose implementation we can't see counts as a solution? Without even showing how to use the library routine to accomplish the stated goal?
LarsH
Maybe you're not showing how to use Interlocked.Exchange to accomplish this because it might be a homework assignment. I'm curious too, though, if @hoang's example doesn't work.
LarsH
@hoang: Your sample should work. What types are `a` and `b`? Do you get an exception or compiler error?
0xA3
@LarsH: See the Hans Passant's answer about the implementation of `Interlocked.Exchange` here: http://stackoverflow.com/questions/3855671/how-do-i-atomically-swap-2-ints-in-c/3855824#3855824
0xA3
@OxA3: It works but i wrapped the call inside a method and forgot to put the ref parameters : the following compile but doesn't work : private void InterlockedSwap(int a, int b) { Interlocked.Exchange(ref b, Interlocked.Exchange(ref a, b)); }
hoang
while this works : private void InterlockedSwap(ref int a, ref int b) { Interlocked.Exchange(ref b, Interlocked.Exchange(ref a, b)); }
hoang
@0xA3: thanks for the answers. So maybe the general solution to the question is "use a library routine that's not written in C# so it doesn't need to use assignment".
LarsH
+3  A: 
class Program
{
    private static void Swap(ref int a, ref int b)
    {
        int.TryParse((a ^ b).ToString(), out a);
        int.TryParse((a ^ b).ToString(), out b);
        int.TryParse((a ^ b).ToString(), out a);
    }

    static void Main(string[] args)
    {
        int a = 42;
        int b = 123;
        Console.WriteLine("a:{0}\nb:{1}", a, b);
        Swap(ref a, ref b);
        Console.WriteLine("a:{0}\nb:{1}", a, b);
    }
}
hoang