XOR трех значений
каков самый простой способ сделать трехсторонний эксклюзив или?
другими словами, у меня есть три значения, и мне нужен оператор, который оценивает только true IFF один из трех значений true.
до сих пор это то, что я придумал:
((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
7 ответов
для ровно трех терминов вы можете использовать следующее выражение:
(a ^ b ^ c) && !(a && b && c)
первая часть true
если один или три термина true
. Вторая часть выражения гарантирует, что не все три 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
a^b^c
только 1, Если неравномерное число переменных равно 1 (два " 1 " будут отменять друг друга). Поэтому вам просто нужно проверить для случая "все три 1":
result = (a^b^c) && !(a&&b&&c)
другая возможность:
a ? !b && !c : b ^ c
который оказывается на 9 символов короче принятого ответа:)
вот общая реализация, которая быстро терпит неудачу, когда более одного 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;
}
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
потому что я могу.