Reputation: 37065
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
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
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
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
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
Reputation: 799014
You have two options here.
Interleave
The original bitmask is spread out, and the new bitmask is inserted in the new "holes".
APAPAPAPAPAPAP
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