40

三方排他的 OR を行う最も簡単な方法は何ですか?

つまり、3 つの値があり、3 つの値のうち 1 つだけが true の IFF と評価されるステートメントが必要です。

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

((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
4

8 に答える 8

49

ちょうど 3 つの項に対して、次の式を使用できます。

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

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

上記の式は、より多くの用語に一般化されていないことに注意してください。より一般的な解決策は、実際に項の数を数えるtrueことです。つまり、次のようになります。

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

return (trueCount == 1); // or some range check expression etc
于 2010-08-12T09:54:05.247 に答える
19
bool result = (a?1:0)+(b?1:0)+(c?1:0) == 1;
于 2010-08-12T09:54:51.500 に答える
9

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

result = (a^b^c) && !(a&&b&&c)
于 2010-08-12T09:53:35.840 に答える
7

別の可能性:

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

これは、受け入れられた回答よりも9文字短くなります:)

于 2010-08-25T12:41:11.103 に答える
2

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

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

于 2014-05-20T07:37:01.347 に答える
2

さらに良いのは、Python の場合:

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

これはif文でも使えます!

Click を介した CLI の相互排他的な引数のおかげで 1 日が節約されました (誰もが Click を嫌っています)。

于 2019-05-19T23:57:41.980 に答える
1
f= lambda{ |a| [false, false, true].permutation.to_a.uniq.include? a }
p f.call([false, true, false])
p f.call([false, true, true])

$真

$偽

出来るからです。

于 2012-11-22T09:11:09.690 に答える
1

複数のboolが見つかった場合にすぐに失敗する一般的な実装を次に示しますtrue

使用法:

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;
}
于 2010-08-28T09:37:59.387 に答える