Is it possible to coerce 0x11 to 0x00, keeping 0x01 -> 0x01 and 0x -> 10 using only bitwise operations?
Question: Is it possible to implement a function that results in this mapping:

    
    
    {
      (0x01, 0x01),
      (0x10, 0x10),
      (0x11, 0x00)
    }
    

Using only bitwise operations?

## Context

In the Flixel framework, there are a set of four constants,

    
    
    FlxObject.LEFT:uint   = 0x0001;
    FlxObject.RIGHT:uint  = 0x0010;
    FlxObject.UP:uint     = 0x0100;
    FlxObject.DOWN:uint   = 0x1000;
    

Obviously designed to be manipulated with bitwise operators. I was trying to
write a function, using only bitwise operators, that would return the opposite
direction of whatever was passed in (in terms of these FlxObject constants).

Some example mappings:

    
    
    {
        (0x0110, 0x1001),
        (0x0100, 0x1000),
        (0x1010, 0x0101),
        (0x0001, 0x0010),
        (0x1100, 0x0000)
    }
    

The problem is, my solution tends to break down when you pass it something
like 0x0011, 0x1100, 0x1110 and similar, and requires a check against this
case. Testing code here (also at <http://pastie.org/3420169>):

    
    
    #!/usr/bin/env python
    
    from sys import stdout
    from os import linesep
    
    # Implementation without conditional
    def horiz(dir):
        return(dir ^ 0x0011 ^ 0x1100) & 0x0011
    
    def vert(dir):
        return (dir ^ 0x1100 ^ 0x0011) & 0x1100
    
    def oppositeDirection(dir):
        return horiz(dir) | vert(dir)
    
    
    # Implementation with conditional
    def horizFix(dir):
        dir = horiz(dir)
        return dir if dir != 0x0011 else 0
    
    def vertFix(dir):
        dir = vert(dir)
        return dir if dir != 0x1100 else 0
    
    def oppositeDirectionFix(dir):
        return horizFix(dir) | vertFix(dir)
    
    failcount = 0
    testcount = 0
    
    def test(dir, expect, func):
        global failcount, testcount
        testcount += 1
        result = func(dir)
        stdout.write('Testing: {0:04x} => {1:04x}'.format(dir, result))
        if result != expect:
            stdout.write('\t GOT {0:04x} expected {1:04x}'.format(result, expect))
            failcount += 1
        stdout.write(linesep)
    
    test_cases =[0x0000, 0x0001, 0x0010, 0x0100, 0x1000, 0x0011, 0x0101, 0x1001, 0x0110, 0x1010, 0x1100, 0x0111, 0x1011, 0x1101, 0x1110, 0x1111] 
    
    
    print 'Testing full oppositeDirection function----------------'
    for case in test_cases:
        test(case, oppositeDirectionFix(case), oppositeDirection)
    
    print '\nTesting horiz function---------------------------------'
    for case in test_cases:
        test(case, horizFix(case), horiz)
    
    print '\nTesting vert function----------------------------------'
    for case in test_cases:
        test(case, vertFix(case), vert)
    
    
    print '{0}Succeeded: {2}/{1}, Failed: {3}/{1}'.format(linesep, testcount, testcount - failcount, failcount)
    

If you run the test, you'll see that in the cases like 0x0011 and 0x0000 horiz
will return 0x0011, and for 0x1100 and 0x000 vert will return 0x1100. So
close!

This is clearly an incredibly insignificant problem, and there will never be
any situation in my game code where a direction value would be simultaneously
left and right or up and down. But, I'm taking this as an opportunity to hone
my bit twiddling skills. Is there some logic principle I'm missing here that
will help me either solve it or realize it's an unsolvable problem?


Answer: No, you have to make some kind of test because your result depends on two
adjacent bits.

You could use `XOR` with `1111` and then test if the result contains `1100` or
`0011`.

But since you only have 16 values to verify would it not be simpler to make a
switch/select/match function for the 8 valid values?

