Today’s fun and games: let’s swap a few variables without using more variables than necessary.
Let me know if you disagree with any of this…
a = 1 b = 2 a, b = b, a puts "a=#{a}, b=#{b}\n" |
my $a = 1; my $b = 2; ($a, $b) = ($b, $a); print "a=$a, b=$b\n"; |
a=1 b=2 a, b = b, a print 'a=%i, b=%i' % (a, b) |
And now, good old C. Let’s use the only method that does not generate an overflow…first, for integer types:
int a=0, b=27; a=(a^(b=(a=a^b)^b)); printf("a=%d, b=%d\n", a, b); |
“Well,” you may say, “but what about pointers arithmetic? Any solution?”
Why, yes. That’s what I came up with after 15 minutes of fiddling:
char *a = "one", *b = "two"; a=(void *)(((long)a)^(long)(b=(void *)(((long)(a=(void *)((long)a^(long)b)))^(long)b))); printf("a=%s, b=%s\n", a, b); |
Note the use of void *, which allows me to ignore the pointer type. And, yes, I know, a C++ compiler may not really like this syntax. This may be doable using templates but I haven’t looked into that.
Sorry, I haven’t looked into Erlang or Haskell yet…







On the PHP one, you could also do:
$a = 1;
$b = 2;
$x = $a
$y = $b
$a = $y
$b = $x
unset($x, $y);
echo ‘a=’,$a’, b=’,$b,”\n”;
Would be interesting to do a test of speed and memory usage between the two.
Of course that wouldn’t be a one liner thou.
I did a test with a 100K loop on each and yours is actually faster by .001 to .005 seconds. I did another test where I removed the unset out of mine and my was .040 – .042 seconds faster. Here’s my test code:
<?php
$time_start = microtime(true);
$i =0;
do
{
$a = 1;
$b = 2;
list($a, $b) = array($b, $a);
}while(++$i < 100000);
$time_end = microtime(true);
$time = $time_end – $time_start;
echo ‘Test 1: ‘,$time,”;
$time_start = microtime(true);
$i =0;
do
{
$a = 1;
$b = 2;
$x = $a;
$y = $b;
$a = $y;
$b = $x;
unset($x, $y);
}while(++$i < 100000);
$time_end = microtime(true);
$time = $time_end – $time_start;
echo ‘Test 2: ‘,$time,”;
$time_start = microtime(true);
$i =0;
do
{
$a = 1;
$b = 2;
$x = $a;
$y = $b;
$a = $y;
$b = $x;
}while(++$i < 100000);
$time_end = microtime(true);
$time = $time_end – $time_start;
echo ‘Test 3: ‘,$time,”;
@EllisGL –
Ha! I do not think that I would have bothered writing a test harness for PHP’s assignment. And, apparently, I would have been wrong: your results are surprising since they show that parsing more code will, in the end, be as fast as calling a built-in function.
@admin –
Hmf I realized, after re-reading your test harness, that the amount of parsing should be the same. Shame on me.
How about using the (little-known) comma operator in your C/C++ examples:
int a = 1;
int b = 27;
a = b – a, b = b – a, a = a + b;
Regarding Erlang, there is no way to do this I know of, as you can bind one variable name only once.
template
void inline swap(T &a, T &b) { T &tmp = a; a = b; b = tmp; }
@Mike M –
Fun alternative. A tad dangerous, though, not because of your use of commas but because your code could suffer from integer overflows.
@manveru –
Right. What was I thinking? I guess I could use an anonymous function to create a new scope but then the swapped result would only live in that other scope, right? (You may have guessed that my knowledge of Erlang is very superficial so far)
@anonymous –
“But that’s cheating!” he whined