corvax
corvax

Reputation: 1145

Implement bitwise operations on arrays

Say I have the following code:

class Restaurant
{
    const FRUITS = 1;
    const VEGETABLES = 2;
    const MEET = 4;

    static public $data = [
        self::FRUITS     => ['apple', 'banana'],
        self::VEGETABLES => ['tomato', 'potato'],
        self::MEET       => ['beef', 'pig']
    ];

    public static function getSomething($byte)
    {
        // unknown logic for me
    }
}

Restaurant::getSomething(Restaurant::FRUITS | Restaurant::MEET);
// ['apple', 'banana', 'beef', 'pig']

I need to implement some logic which makes join operations based on bitwise operations.

What is the best way to do that?

Upvotes: 1

Views: 107

Answers (2)

h2ooooooo
h2ooooooo

Reputation: 39542

Use ($byte & $bw) === $bw where $byte is whatever value you're testing with (eg. 3) and $bw is your bitwise value (eg. 1, 2 or 4) to check if bitwise values match.

Why does it work?

It's fairly simple. When we AND items, we're only using the bit values that are present in both values

$byte  = 3 = 0011
$bw    = 2 = 0010
AND'ed = 2 = 0010 (the same as $bw - $bw is included!)
               ^ 1 & 1 = 1
-----------------

$byte  = 5 = 0101
$bw    = 2 = 0010
AND'ed = 0 = 0000 (empty as the values do not match - $bw is NOT included)
               ^ 0 & 1 = 0

Code:

<?php

class Restaurant
{
    const FRUITS     = 1; // 0001
    const VEGETABLES = 2; // 0010
    const MEET       = 4; // 0100

    static public $data = [
        self::FRUITS     => ['apple', 'banana'],
        self::VEGETABLES => ['tomato', 'potato'],
        self::MEET       => ['beef', 'pig']
    ];

    public static function getSomething($byte)
    {
        // Start with an empty array
        $returnItems = array();

        // Loop through our bitwise values
        foreach (self::$data as $bw => $items) {

            // Is it included in $byte?
            if (($byte & $bw) === $bw) {

                // Then add the items in $items to $returnItems
                $returnItems = array_merge($returnItems, $items);
            }
        }

        // Return the items
        return $returnItems;
    }
}

Test:

$result = Restaurant::getSomething(Restaurant::FRUITS | Restaurant::MEET); // 5 - 0101

var_dump($result);

/*
    array(4) {
      [0]=>
      string(5) "apple"
      [1]=>
      string(6) "banana"
      [2]=>
      string(4) "beef"
      [3]=>
      string(3) "pig"
    }
*/

DEMO

Upvotes: 4

David Triebe
David Triebe

Reputation: 375

Nothing too fancy I'd say...

public static function getSomething($bitmask)
{
    $result = [];
    foreach(self::$data as $key => $value)
    {
        if(($key & $bitmask) !== 0)
        {
            $result = array_merge($result, $value);
        }
    }

    return $result;
}

Upvotes: 1

Related Questions