SPUG: Re: scalar swap challenge (SPOILER!)

Michael R. Wolf MichaelRWolf at att.net
Thu Oct 9 17:52:50 CDT 2003


Creede Lambard <creede at penguinsinthenight.com> writes:

[...]

 push @_, $y, $x; ($y, $x) = (pop, pop);

[...]

> $ENV{FOO} = $x;
> $ENV{BAR} = $y;
> $y = $ENV{FOO};
> $x = $ENV{BAR};

[...]

> A mail from Michael a few minutes ago informed me that he was trying to
> eschew temporary storage of any kind, so I'm trying to think outside that
> particular box.

Well, I was trying to eschew *explicit* temporary storage. Temporary
storage *must* exist, even if it's unnamed temporary storage that the
compiler generates for intermediate results.

As a puzzle, it was intended to remove *explicit* temporary storage.
In that case some of the solutions (using @_, @ARGV, or %ENV) don't
pass, but as a puzzle, it was (see my tag line) meant to be a playful
way to learn. It's the what-if's that are interesting to me, and it
was interesting to see how others bent and reinterpreted the rules. If
you had fun or your learned, you won!!!!

I learned a lot from working it myself. As an aside, when I was
initially presented with the puzzle, I *almost* asked the answer, but
resisted. I wanted to push against it rather than just be given the
answer. I'm glad I did. Then out of (seemingly) nowhere, the solution
just occurred to me. Really weird. I hadn't heard this trick before,
but I knew enough of bit manipulations from my assembler days that I
remembered the toggling trick of XOR. After not finding xor to be
useful (but still taking up grey matter) for 20ish years, it occurred
to me, and I scribbled down this simple binary math XOR rambling to
prove that all permutations of 0 and 1 worked.

0011 a
0101 b
----
0110 a^b -> a
0101 b
----
0011 a^b -> b
0110 a
----
0101 b^a -> a


Two things impressed me:

 - Not focusing on it had the answer appear.  The value of peripheral
 thinking, or my subconscious.

 - The similarity to superposition of waves -- it feels to me like two
 values looking at each other through a glass wall, then passing
 through it to the other side, superposing in the middle then coming
 through it unchanged to the other side.  Wow!  Whew! COoooolllll.


My final obfuscated solution is this:

    $a ^= $b ^= $a ^= $b;

And if I were playing golf:

    $a^=$b^=$a^=$b;


(But I would *NOT* code it this way, not even with great comments.)


But the destination doesn't show the journey.  Here's the journey:

    # Original solution:
    #    $a = $a ^ $b;
    #    $b = $b ^ $a;
    #    $a = $a ^ $b;

    # Refined to use op=
    #    $a ^= $b;
    #    $b ^= $a;
    #    $a ^= $b;

    # Utilizing op= value, factored onto one line
    #    $a ^= ($b ^= ($a ^= $b));

    # Refined to remove unnecessary parens
    $a ^= $b ^= $a ^= $b;


-- 
Michael R. Wolf
    All mammals learn by playing!
        MichaelRWolf at att.net




More information about the spug-list mailing list