language-agnostic - operadores - xor c#
XOR de tres valores (7)
¿Cuál es la forma más simple de hacer un quirófano exclusivo de tres vías?
En otras palabras, tengo tres valores, y quiero una declaración que evalúe a IFF verdadero, solo uno de los tres valores es verdadero.
Hasta ahora, esto es lo que se me ocurrió:
((a ^ b) && (a ^ c) &&! (b && c)) || ((b ^ a) && (b ^ c) &&! (a && c)) || ((c ^ a) && (c ^ b) &&! (a && b))
¿Hay algo más simple para hacer lo mismo?
Aquí está la prueba de que lo anterior logra la tarea:
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
Aquí hay una implementación general que falla rápidamente cuando se encuentra que más de un bool
es true
.
Uso :
XOR(a, b, c);
Código :
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;
}
Otra posibilidad:
a ? !b && !c : b ^ c
que resulta ser 9 caracteres más cortos que la respuesta aceptada :)
Para exactamente tres términos, puede usar esta expresión:
(a ^ b ^ c) && !(a && b && c)
La primera parte es true
si uno o tres de los términos son true
. La segunda parte de la expresión garantiza que no todos los tres son true
.
Tenga en cuenta que la expresión anterior NO se generaliza a más términos. Una solución más general es contar realmente cuántos términos son true
, así que algo como esto:
int trueCount =
(a ? 1 : 0) +
(b ? 1 : 0) +
(c ? 1 : 0) +
... // more terms as necessary
return (trueCount == 1); // or some range check expression etc
También puedes probar (en C):
!!a + !!b + !!c == 1
a^b^c
es solo 1 si un número impar de variables es 1 (dos ''1'' se cancelarían mutuamente). Entonces solo necesita verificar el caso "los tres son 1":
result = (a^b^c) && !(a&&b&&c)
bool result = (a?1:0)+(b?1:0)+(c?1:0) == 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
$ falso
Porque puedo.