I need to do an xor conditional between 3 values, ie i need one of the three values to be true but not more than one and not none.
I thought i could use the xor ^ op
Came across this while I went down the wrong path trying to solve my own problem (XOR across 4 values); decided that LINQ is the simplest way to handle this problem for an N-case;
bool OneAndOnlyOneIsTrue(IEnumerable<bool> conditions)
{
return conditions.Count(c => c) == 1;
}
Invoked like;
bool OneLuckyGuy(Person p1, Person p2, Person p3, Person p4)
{
return OneAndOnlyOneIsTrue(new [] {
p1.IsAMan(),
p2.IsAMan(),
p3.IsAMan(),
p4.IsAMan()
});
}
Instruction-wise, this will check each condition once, so function is O(n), but it's flexible and a damn site more readable than the bitwise alternative. ;-)
XOR is a binary operator, it can only be used on 2 values at a time. So when you do (true XOR true XOR true)
, it actually does ((true XOR true) XOR true)
...
The inner (true XOR true)
resolves to false
because they're the same. With that resolved, the remainder is (false XOR true)
, which resolves to true
.
It sounds like you're trying to be clever or super-efficient about matching your conditions. This would probably take me several minutes to puzzle out and then write a truth-table or test to make sure it treats all possible combinations correctly.
It is so much simpler to just count how many of them are true
and do if (countTrues == 1)
. The reason for this is that it doesn't have significant overhead, and it is actually readable and understandable compared to a solution using only bit-twiddling (there are a couple other answers here that demonstrate it).
((true ^ true) ^ true)
will return true
, which is not what you would expect from true ^ true ^ true
.
To make sure that you get the outcome you want (only one value to be true) do the following:
if ((a && !b && !c) || (!a && b && !c) || (!a && !b && c))
Alternatively, based on @jcomeau_ictx answer, you can do the following:
if( Convert.ToInt32(a) + Convert.ToInt32(b) + Convert.ToInt32(c) == 1 )
Or, you could create a function:
public bool TernaryXor(bool a, bool b, bool c)
{
//return ((a && !b && !c) || (!a && b && !c) || (!a && !b && c));
// taking into account Jim Mischel's comment, a faster solution would be:
return (!a && (b ^ c)) || (a && !(b || c));
}
EDIT: You might want to name the function TernaryXor
so that it is more clear as to the outcome of the function.
the solution simple it's
a = true; b = false; c = true
(a ^ b) || (a ^ c)