One-line variables swap in PHP, Ruby, Perl, Python and C
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…
Similar Posts:
- Java Does Pass-By-Reference
- PON or “PHP Object Notation” Is Already Here
- C!D v2 = nextBBS multi
- Flex: How I worked around MOUSE_OUT’s inefficiencies
- Google Chrome: an index of what developers need to know (good and bad)
If you enjoyed this post, make sure you subscribe to my RSS feed!
If you enjoyed this post, please consider to leave a comment or subscribe to the feed and get future articles delivered to your feed reader.
Comments
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.
@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)
“But that’s cheating!” he whined








May 10, 2009 @ 8:52 pm
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.