Quiero devolver True
si y solo si 3 de los 4 valores booleanos son verdaderos.
Lo más cerca que he llegado es (x ^ y) ^ (a ^ b)
:
¿Qué tengo que hacer?
boolean-logic
Simon Kuang
fuente
fuente
not a ^ not b ^ not c ^ not d
es verdadera cuando exactamente uno de los valores negados es verdadero. Esto significa que, a partir de los valores originales, exactamente uno era falso.(!a&&b&&c&&d) || (a&&!b&&c&&d) || (a&&b&&!c&&d) || (a&&b&&c&&!d)
.Respuestas:
Sugiero escribir el código de una manera que indique lo que quieres decir. Si desea que 3 valores sean verdaderos, me parece natural que el valor 3 aparezca en algún lugar.
Por ejemplo, en
C++
:Esto está bien definido en
C++
:standard (§4.7/4)
indica que convertirbool
aint
da los valores esperados 0 o 1.En Java y C #, puede usar la siguiente construcción:
fuente
if (!!a + !!b + !!c + !!d == 3)
es más fácil de escribir, aunque no sé si los compiladores optimizan esto o no# 1: ¿Usando una ramificación?: 3 o 4 operaciones
# 2 no ramificado, 7 operaciones
Cuando solía perfilar todo, descubrí que las soluciones no ramificadas eran un poco más rápidas de operación por operación, ya que la CPU podía predecir mejor la ruta del código y ejecutar más operaciones en conjunto. Sin embargo, aquí hay un 50% menos de trabajo en la declaración de ramificación.
fuente
Si esto hubiera sido Python, habría escrito
O
O
O
O
O
O
Todo esto funciona, ya que los booleanos son subclases de enteros en Python.
O, inspirado en este ingenioso truco ,
fuente
a=5;not not a == 1
. La desventaja de no tener un tipo booleano real.bool
:)Forma normal larga pero muy simple (disyuntiva):
Puede simplificarse, pero eso requiere más reflexión: P
fuente
(a & b & (c ^ d)) | ((a ^ b) & c & d)
?No estoy seguro de que sea más simple, pero tal vez.
((x xor y) and (a and b)) or ((x and y) and (a xor b))
fuente
Si desea utilizar esta lógica en un lenguaje de programación, mi sugerencia es
O si lo desea, puede poner todo esto en una sola línea:
También puede generalizar este problema a
n of m
:fuente
Esta respuesta depende del sistema de representación, pero si 0 es el único valor interpretado como falso y
not(false)
siempre devuelve el mismo valor numérico, entoncesnot(a) + not(b) + not(c) + not(d) = not(0)
debería funcionar.fuente
Teniendo en cuenta que SO si para preguntas de programación, en lugar de simples problemas lógicos, la respuesta obviamente depende de la elección de un lenguaje de programación. Algunos idiomas admiten funciones que son poco comunes a otros.
Por ejemplo, en C ++ puede probar sus condiciones con:
Esta debería ser la forma más rápida de hacer la verificación en los idiomas que admiten la conversión automática (de bajo nivel) de tipos booleanos a enteros. Pero, de nuevo, no hay una respuesta general para ese problema.
fuente
Lo mejor que puedo hacer es
((x ^ y) ^ (a ^ b)) && ((a || x) && (b || y))
fuente
La expresión de puño busca 1 o 3
true
de 4. La segunda elimina 0 o 1 (y a veces 2)true
de 4.fuente
Java 8, filtre los valores falsos y cuente los valores verdaderos restantes:
Entonces puede usarlo de la siguiente manera:
Generaliza fácilmente a la comprobación de
n
dem
artículos de ser cierto.fuente
Para verificar que al menos
n
todosBoolean
son verdaderos, (n debe ser menor o igual que el número total deBoolean
: p)Editar : después del comentario de @ Cruncher
Para verificar 3
boolean
de 4Otro :
((c & d) & (a ^ b)) | ((a & b) & (c ^ d))
( Detalles )fuente
Aquí hay una manera de resolverlo en C # con LINQ:
fuente
Esa es la función booleana simétrica
S₃(4)
. Una función booleana simétrica es una función booleana que solo depende de la cantidad de entradas establecidas, pero no depende de las entradas que sean. Knuth menciona funciones de este tipo en la sección 7.1.2 del Volumen 4 de The Art of Computer Programming.S₃(4)
se puede calcular con 7 operaciones de la siguiente manera:Knuth muestra que esto es óptimo, lo que significa que no puede hacerlo en menos de 7 operaciones utilizando los operadores normales:
&&, || , ^, <,
y>
.Sin embargo, si desea usar esto en un lenguaje que use
1
verdadero y0
falso, también puede usar la suma fácilmente:lo que deja tu intención bastante clara.
fuente
Desde un punto de vista de lógica pura, esto es lo que se me ocurrió.
Según el principio del palomar, si exactamente 3 son verdaderas, entonces ayb son verdaderas, o cyd son verdaderas. Entonces es solo cuestión de combinar cada uno de esos casos con exactamente uno de los otros 2.
Tabla de verdad de Wolfram
fuente
mine <=> his
no sé qué decir, ya que esto sería de esperar.Si utiliza una herramienta de visualización lógica como Karnaugh Maps, verá que este es un problema en el que no puede evitar un término lógico completo si desea escribirlo en una línea if (...). Lopina ya lo mostró, no es posible escribirlo de manera más simple. Puede factorizar un poco, pero seguirá siendo difícil de leer para usted y para la máquina.
Las soluciones de conteo no son malas y muestran lo que realmente buscas. La forma de contar eficientemente depende de su lenguaje de programación. Las soluciones de matriz con Python o LinQ son agradables de ver, pero cuidado, esto es LENTO. Wolf's (a + b + x + y) == 3 funcionará bien y rápido, pero solo si su idioma equivale a "verdadero" con 1. Si "verdadero" está representado por -1, deberá probar para -3: )
Si su idioma usa booleanos verdaderos, puede intentar programarlo explícitamente (¡uso! = Como prueba XOR):
"x! = y" funciona solo si x, y son de tipo booleano. Si son de otro tipo donde 0 es falso y todo lo demás es verdadero, esto puede fallar. Luego use un XOR booleano, o ((bool) x! = (Bool) y), o escriba "if (x) return (y == false) else return (y == true);", que es un poco más trabajar para la computadora
Si su lenguaje de programación proporciona el operador ternary?: Puede acortarlo a
lo que mantiene un poco de legibilidad, o lo corta agresivamente
Este código hace exactamente tres pruebas lógicas (estado de a, estado de b, comparación de x e y) y debería ser más rápido que la mayoría de las otras respuestas aquí. Pero necesitas comentarlo, o no lo entenderás después de 3 meses :)
fuente
Hay muchas buenas respuestas aquí; Aquí hay una formulación alternativa que nadie más ha publicado todavía:
fuente
Similar a la primera respuesta, pero Java puro:
Prefiero contarlos como enteros porque hace que el código sea más legible.
fuente
En Python , para ver cuántos elementos iterables son verdaderos, use
sum
(es bastante sencillo):Preparar
Prueba real
Salida
fuente
Si buscas la solución en el papel (sin programación), entonces los mapas K y los algoritmos Quine-McCluskey son lo que buscas, te ayudan a minimizar tu función booleana.
En su caso, el resultado es
Si desea hacer esto programáticamente, una cantidad no fija de variables y un "umbral" personalizado, simplemente iterar a través de una lista de valores booleanos y contar las ocurrencias de "verdadero" es bastante simple y directo.
fuente
Dados los 4 valores booleanos, a, b, x, y, esta tarea se traduce en la siguiente instrucción C:
fuente
true
igual a 1. Esto no es cierto (sin juego de palabras) en todos los idiomas / casos. blogs.msdn.com/b/oldnewthing/archive/2004/12/22/329884.aspxes lo que quieres Básicamente tomé su código y agregué verificar si realmente 3 son verdaderos y no 3 son falsos.
fuente
¿Una pregunta de programación sin una respuesta que implique recursividad? ¡Inconcebible!
Hay suficientes respuestas "exactamente 3 de 4 verdaderas", pero aquí hay una versión generalizada (Java) para "exactamente m de n verdaderas" (de lo contrario, la recursión realmente no vale la pena) solo porque puede:
Esto podría llamarse con algo como:
que debería regresar
true
(porque 5 de 8 valores eran verdaderos, como se esperaba). No estoy muy contento con las palabras "verdaderas" y "falsas", pero no puedo pensar en un nombre mejor en este momento ... Tenga en cuenta que la recursión se detiene cuando se han encontrado demasiadostrue
o demasiadosfalse
valores.fuente
true
. Quizás algo asícontainsNumberOfTrueValues()
. Como acotación al margen: nombres de Smalltalk sería mucho más adecuado para esto, sin embargo:doesArray: someBooleans startingAt: anIndex containNumberOfTrueValues: anExpectedNumber foundSofar: aNumberFoundSoFar
. Probablemente demasiado tiempo para los gustos de algunos desarrolladores de Java, pero Smalltalkers nunca tienen miedo de nombrar adecuadamente ;-)containsTruth
significa "contiene una cantidad no revelada de verdad", literalmente, así que creo que está bastante bien.Dado que la legibilidad es una gran preocupación, podría usar una llamada de función descriptiva (envolviendo cualquiera de las implementaciones sugeridas). Si este cálculo debe hacerse en varios lugares, una llamada a la función es la mejor manera de lograr la reutilización y deja en claro exactamente lo que está haciendo.
fuente
En PHP, hacerlo más dinámico (en caso de que cambie el número de condiciones, etc.):
fuente
Si bien podría demostrar que esta es una buena solución, la respuesta de Sam Hocevar es fácil de escribir y comprender más tarde. En mi libro eso lo hace mejor.
fuente
Aquí hay un código C # que acabo de escribir porque me has inspirado:
Toma cualquier cantidad de argumentos y le dirá si n de ellos son verdaderos.
y lo llamas así:
Entonces ahora puede probar 7/9 o 15/100 como lo hará.
fuente