Anthony
Anthony

Reputation: 37065

In PHP (or any language), Can 2 bitmasks be merged while maintaining "identity" of orignal bits?

This may be a really silly question, but it just crossed my mind and I thought it would be interesting to know for sure....

So here is the scenario:

Users have 3 options for each day of the week: AM, PM, and OFF. These are mutually exclusive choices, so there is no option to work both an AM and PM on same day.

So if I wanted to store their AM shifts and PM shifts as separate bitmasks, and User1 chooses the following:

 S    M   T   W   Th   F   Sa
 A    P   X   A   X    P   A

I would have the following:

 $shifts['User1']['AM'] = 73;  //  1001001
 $shifts['User1']['PM'] = 34;  //  0100010

Now, if I just wanted to know which days User1 worked, I could obviously just do:

 $shifts['User1']['All'] = $shifts['User1']['AM'] | $shifts['User1']['PM'];

Or even just:

 $shifts['User1']['All'] = $shifts['User1']['AM'] + $shifts['User1']['PM'];

But what if I wanted the final result to distinguish AM from PM, something to the effect of:

 $shifts['User1']['AM'] = A00A00A;
 $shifts['User1']['PM'] = 0P000P0;

So that the A's and P's are both considered set, but that

 A00A00A | 0P000P0 = AP0A0PA;

Is there a common way of doing this, or am I thinking about this totally wrong?

Upvotes: 2

Views: 309

Answers (5)

Telmo Marques
Telmo Marques

Reputation: 5106

To represent three states in a binary fashion you need 2 bits. For instance, you could say that:

PM = 01

AM = 10

OFF = 00

So now you have this:

A00A00A translates to 10 00 00 10 00 00 10

0P000P0 translates to 00 01 00 00 00 01 00

Applying bitwise OR operation:

10 00 00 10 00 00 10
00 01 00 00 00 01 00
--------------------
10 01 00 10 00 01 10
A  P  0  A  0  P  A

You get AP0A0PA, your desired result.

Upvotes: 1

Paul
Paul

Reputation: 6871

minitech's comment is correct. This is a ternary number system (because you have 3 choices for each value). So you could do this:

$shifts['User1']['AM'] = '1001001';  //  A00A00A
$shifts['User1']['PM'] = '0200020';  //  0P000P0

$all = intval($shifts['User1']['AM'], 3) +
    intval($shifts['User1']['PM'], 3);

echo base_convert($all, 10, 3);

Upvotes: 1

Tadeck
Tadeck

Reputation: 137410

Yes, it is possible. See the example below in Python:

>>> class WorkShift(str):
    def __or__(self, val):
        def shift_calc(x, y):
            return x if x != '0' else y
        return WorkShift(''.join(map(shift_calc, self, val)))

>>> WorkShift('A00A00A') | WorkShift('0P000P0')
'AP0A0PA'

Does it answer your question?

Ps. I used Python since you explicitly stated it can be any programming language. I overloaded | operator. Result of the operation is still WorkShift's instance, so you can use it for further processing. It also inherits from str, so you can use it as string as well.

EDIT:

Similar solution for PHP, but without operator overloading, based only on strings processing:

<?php

function shift_calc($x, $y) {
    return $x != '0' ? $x : $y;
};

function shift_sum($am, $pm) {
    return implode(array_map('shift_calc', str_split($am), str_split($pm)));
};

$result = shift_sum('A00A00A', '0P000P0');

where the $result is a string with the following value: "AP0A0PA" (see proof here: http://ideone.com/NbTEJ).

Upvotes: 1

Paul
Paul

Reputation: 6871

To write a literal value in binary use: 0b1001001, or hex: 0x49, instead of decimal: 73.

The bitmap will only ever give you true or false, so there is no way to represent three values (AM, PM, X) by compressing two bitmaps into one.

I think you are thinking about this wrong (others may have a smarter solution that I can't think of though). An array of characters A, P, X might be as good for this. You can merge arrays (so it is not the same as a string).

Upvotes: 1

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 799014

You have two options here.

  1. Interleave

    The original bitmask is spread out, and the new bitmask is inserted in the new "holes".

    APAPAPAPAPAPAP
    
  2. Append

    The new bitmask is appended to the old bitmask.

    AAAAAAAPPPPPPP
    

The former is easier to inspect/compare, but the latter is more efficient with regards to speed.

Upvotes: 0

Related Questions