Search code examples
pythonternary

How to merge two binary numbers into a ternary number


I have two binary integers, x0 and x1 that are 8 bits (so they span from 0 to 255). This statement is always true about these numbers: x0 & x1 == 0. Here is an example:

bx0 = 100 # represented as 01100100 in binary
bx1 = 129 # represented as 10000001 in binary

So I need to do the following operation on these numbers. First, interpret these binary representations as ternary (base-3) numbers, as follows:

tx0 = ternary(bx0) # becomes  981 represented as 01100100 in ternary
tx1 = ternary(bx1) # becomes 2188 represented as 10000001 in ternary

Then, swap all of the 1 in the ternary representation of tx1 to 2:

tx1_swap = swap(tx1) # becomes 4376, represented as 20000002 in ternary

Then use a ternary version of OR on them to get the final combined number:

result = ternary_or(tx0, tx1_swap) # becomes 5357, represented as 21100102 in ternary

I don't need the ternary representation saved at any point, I only need the result, where for example result=5357. Of course I could code this by converting the numbers to binary, converting to ternary, etc.. but I need this operation to be fast because I am doing this many times in my code. What would a fast way to implement this in python?


Solution

  • Re-explanation for dummies like me:

    A straightforward way to "encode" two binary mutually exclusive numbers (w & b == 0) in ternary would be:

    white_black_empty = lambda w, b: int(format(b, 'b'), base=3) + \
                                     int(format(w, 'b').replace('1','2'), base=3)
    

    Here are all possible 2-bit variants:

    white_black_empty(0b00, 0b00) == 0
    white_black_empty(0b00, 0b01) == 1
    white_black_empty(0b01, 0b00) == 2
    white_black_empty(0b00, 0b10) == 3
    white_black_empty(0b00, 0b11) == 4
    white_black_empty(0b01, 0b10) == 5
    white_black_empty(0b10, 0b00) == 6
    white_black_empty(0b10, 0b01) == 7
    white_black_empty(0b11, 0b00) == 8
    

    By observing that int(format(w, 'b').replace('1','2'), base=3) is actually equal to double of int(format(w, 'b'), base=3) (for example, 20220023 == 10110013*2), we get the solution that @Mark Dickinson posted in the comments above:

    white_black_empty = lambda w, b: int(format(b, 'b'), base=3) + \
                                     int(format(w, 'b'), base=3)*2