2011-12-26 7 views
2

バイト配列(つまりchar)のビットが同じタイプの別の配列のサブセットであるかどうかを確認する必要があります。たとえば、0001.0011(19) 0011.0011(51)のサブセットであり、0000.1011(11)はそうではない。バイナリ配列がC内の別の配列のサブセットであるかどうかを確認

私はビット演算で遊んで開始し、ほとんどXOR/OR/XOR配列とそれを解決:

int is_subset (char *set_a, char *set_b, int size) 
{ 
    /* The operation is performed with three bitwise operations, resulting in a 
    * sequence of bits that will be equal to zero if set_a is a subset of 
    * set_b. As a bonus, the positions where the sets differ will be 
    * available in the resulting sequence, and thus the number of differing 
    * positions can be obtained by counting the number of bits set (for exemple, 
    * with __builtin_popcount in GCC). 
    * 
    * Exemple (TRUE):    Exemple (FALSE): 
    * ================    ================ 
    * set_a 00010011    set_a 00001011 
    * set_b 00110011    set_b 00110011 
    * ----------------    ---------------- 
    * XOR  00100000    XOR  00111000 
    * set_b 00110011    set_b 00110011 
    * ----------------    ---------------- 
    * OR  00110011    OR  00111011 
    * set_b 00110011    set_b 00110011 
    * ----------------    ---------------- 
    * XOR  00000000    XOR  00001000 
    */ 

    int i; 
    for (i = 0; i < size; i++) 
    if ((((set_a[i]^set_b[i]) | set_b[i])^set_b[i]) != 0) 
     return FALSE; 

    return TRUE; 
} 

しかしset_aがゼロ(0000.0000)である場合には(常にTRUEを返す)は失敗します。私は別の戦略(ブルームフィルターなど)を試みましたが、おそらく私のプログラミングスキルのために、それは速く、少なくとも優雅にはほど遠いものでした。

例外なくこれを行う標準的でエレガントな方法はありますか?

EDIT:この文脈では、「サブセット」は、第1の配列(set_a)のTRUEビットがすべて第2のもの(TRUE)であることを意味する。 2番目の配列にTRUEという別のビットがあるかもしれませんが、最初の配列ではFALSEかどうかは関係ありません。

+1

の特殊なケースを除外すべきであるおそらく、私は、問題の何かが欠けているんだけど、Aのあなたの定義は何ですかこの文脈でサブセット? – Corbin

+0

申し訳ありませんが、質問を編集しました! – Giacomo

+1

サブセットの定義が、あなたのコードで判断していると思われる場合は、配列で私たちを悩ますべきではありません。そして、あなたは '1'ビットintの別のintの '1'ビットのサブセットです。 –

答えて

4

私はビューの純粋に理論的な数学的な観点から、空のセットがいずれかのサブセットであるため、set_aは、ゼロの配列である場合にはTRUEを返しますので、あなたのコードがちょうどを失敗したと言うことは正しいことを確認していません他のセット。それが気に入らない場合は、set_aが0の配列であるかどうかを確認するために追加のチェックを追加してください。そうであれば、FALSEをすぐに返してください。

4

abのサブセットであるa内の各ビットはb

a -> b 

又は同等の対応するビットを意味し、

~a | b //not a or b 

1111111を与えるべきです。

テスト私はしないでください(私たちはBではないが、中に設定されたビットを持って何の例がないかどうかをチェックする)

0 == (a & ~b) 

int is_subset (char *set_a, char *set_b, int size) 
{ 
    int i; 
    for (i = 0; i < size; i++){ 
    if(0 != (set_a[i] & (~ set_b[i]))) 
     return FALSE; 
    } 
    return TRUE; 
} 

ものの否定againsのゼロは単純かもしれませんビットごとのものが文字で正しく動作するかどうか、または符号なしのものに最初にキャストする必要があるかどうかを覚えておいてください。

+0

set_aが配列の0であれば、私のコードよりもずっと優れていますが、それ以外は? – Giacomo

+0

Giacomoが正しい:set_aがゼロの場合、あなたのソリューションは常にtrueを返します。 –

+0

@Giacomo:しかし、あなたの定義では、missingnoの解決策が正しいかどうかは不明です。あなたの定義を非常に厳密に読んで、彼の解決策は正しいです。 –

2

aのサブセットはbで、a | b == bの場合のみです。この条件が各バイトで満たされる場合は、TRUEを返します。それ以外の場合はFALSEを返します。

+0

あるいは、 'a&b == a'の場合にのみ、 –

+0

すばらしい答え...これは厳密なサブセット(つまり等価がfalseを返す)になるようにこれを修正する方法を知っていますか? – swami

0

技術的なトリビア、あなたの表現の左側にある「& &を(theSubsetUnderTest)」を追加すると、0

関連する問題