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
正確に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
bool result = (a?1:0)+(b?1:0)+(c?1:0) == 1;
a^b^c
は、変数の数が不均一な場合は1のみです(2つの「1」は互いに打ち消し合います)。したがって、「3つすべてが1」の場合を確認する必要があります。
result = (a^b^c) && !(a&&b&&c)
別の可能性:
a ? !b && !c : b ^ c
たまたま受け入れられた答えより9文字短いです:)
(Cで)試すこともできます:
!!a + !!b + !!c == 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])
$ true
$ false
出来るからです。
これは、複数の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;
}
Pythonではさらに良い:
result = (1 if a else 0)+(1 if b else 0)+(1 if c else 0) == 1
これはifステートメントでも使用できます!
Clickを介したCLIの相互に排他的な引数のために私の一日を節約しました(誰もがクリックを嫌います)