web-dev-qa-db-ja.com

XOR 3つの値の

3方向排他的論理和を実行する最も簡単な方法は何ですか?

つまり、3つの値があり、真のIFFのみに評価されるステートメントが必要ですone 3つの値のうち真です。

これまでのところ、これは私が思いついたものです:

((a ^ b)&&(a ^ c)&&!(b && c))|| ((b ^ a)&&(b ^ c)&&!(a && c))|| ((c ^ a)&&(c ^ b)&&!(a && b))

同じことをするのにもっと簡単なことはありますか?


上記がタスクを達成するという証拠は次のとおりです。

a = true; b = true; c = true
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> false

a = true; b = true; c = false
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> false

a = true; b = false; c = true
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> false

a = true; b = false; c = false
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> true

a = false; b = true; c = true
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> false

a = false; b = true; c = false
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> true

a = false; b = false; c = true
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> true

a = false; b = false; c = false
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> false
35
Josh

正確に3つの用語については、次の式を使用できます。

(a ^ b ^ c) && !(a && b && c)

用語の1つまたは3つがtrueである場合、最初の部分はtrueです。式の2番目の部分は、3つすべてがtrueではないことを保証します。

上記の式は[〜#〜] not [〜#〜]より多くの用語に一般化することに注意してください。より一般的な解決策は、実際にはcounttrueの用語の数なので、次のようになります。

int trueCount =
   (a ? 1 : 0) +
   (b ? 1 : 0) +
   (c ? 1 : 0) +
   ... // more terms as necessary 

return (trueCount == 1); // or some range check expression etc
43
bool result = (a?1:0)+(b?1:0)+(c?1:0) == 1;
14
Hemant

a^b^cは、変数の数が不均一な場合は1のみです(2つの「1」は互いに打ち消し合います)。したがって、「3つすべてが1」の場合を確認する必要があります。

result = (a^b^c) && !(a&&b&&c)
9
Aaron Digulla

別の可能性:

a ? !b && !c : b ^ c

たまたま受け入れられた答えより9文字短いです:)

6
Timwi

(Cで)試すこともできます:

!!a + !!b + !!c == 1

2
kaspersky
f= lambda{ |a| [false, false, true].permutation.to_a.uniq.include? a }
p f.call([false, true, false])
p f.call([false, true, true])

$ true

$ false

出来るからです。

1
nurettin

これは、複数のbooltrueであることが判明した場合にすぐに失敗する一般的な実装です。

使用法

XOR(a, b, c);

コード

public static bool XOR(params bool[] bools)
{
    return bools.Where(b => b).AssertCount(1);
}

public static bool AssertCount<T>(this IEnumerable<T> source, int countToAssert)
{
    int count = 0;
    foreach (var t in source)
    {
        if (++count > countToAssert) return false;
    }

    return count == countToAssert;
}
1
Ani

Pythonではさらに良い:

result = (1 if a else 0)+(1 if b else 0)+(1 if c else 0) == 1

これはifステートメントでも使用できます!

Clickを介したCLIの相互に排他的な引数のために私の一日を節約しました(誰もがクリックを嫌います)

0