Un entrevistador me hizo esta pregunta recientemente: dadas tres variables booleanas, a, byc, devuelven verdadero si al menos dos de los tres son verdaderos.
Mi solución sigue:
boolean atLeastTwo(boolean a, boolean b, boolean c) {
if ((a && b) || (b && c) || (a && c)) {
return true;
}
else{
return false;
}
}
Dijo que esto se puede mejorar aún más, pero ¿cómo?
java
boolean
boolean-logic
usuario282886
fuente
fuente
atLeastTwo(iWantYou, iNeedYou, imEverGonnaLoveYou)
Respuestas:
En lugar de escribir:
Escribir:
En cuanto a la expresión en sí, algo como esto:
o esto (lo que sea más fácil de entender):
Prueba
a
yb
exactamente una vez, yc
como máximo una vez.Referencias
fuente
return hasGoodAttendance ? (passedCoursework || passed Exam) : (passedCoursework && passedExam)
, eso me parece bien.atLeastTwo(hasgoodAttendance, passedCoursework, passedExam)
. La idea de "al menos 2 bools son verdaderas" es lo suficientemente genérica como para merecer su propia función.Solo por el uso de XOR para responder a un problema relativamente sencillo ...
fuente
¿Por qué no implementarlo literalmente? :)
En C podrías simplemente escribir
a+b+c >= 2
(o!!a+!!b+!!c >= 2
para estar muy seguro).En respuesta a la comparación de TofuBeer del código de bytes de Java, aquí hay una prueba de rendimiento simple:
Esto imprime lo siguiente en mi máquina (ejecutando Ubuntu en Intel Core 2 + sun java 1.6.0_15-b03 con HotSpot Server VM (14.1-b02, modo mixto)):
Primera y segunda iteraciones:
Iteraciones posteriores:
Me pregunto, ¿qué podría hacer Java VM que degrada el rendimiento con el tiempo para el caso (a + b + c> = 2).
Y esto es lo que sucede si ejecuto Java con un
-client
conmutador VM:Misterio...
Y si lo ejecuto en GNU Java Interpreter , se vuelve casi 100 veces más lento, pero la
a&&b || b&&c || a&&c
versión gana.Resultados de Tofubeer con el último código que ejecuta OS X:
Resultados de Paul Wagland con una Mac Java 1.6.0_26-b03-383-11A511
fuente
a+b+c >= 2
: esto no funciona con negativos, ¿verdad? Puede que tenga que hacer la!!a
cosa, no estoy seguro.Este tipo de preguntas se pueden resolver con un mapa de Karnaugh :
de lo cual deduce que necesita un grupo para la primera fila y dos grupos para la primera columna, obteniendo la solución óptima de poligenelubricantes:
fuente
La legibilidad debe ser el objetivo. Alguien que lea el código debe comprender su intención de inmediato. Entonces aquí está mi solución.
fuente
Seq(true, true, false).map(if (_) 1 else 0).sum >= 2
Explicación:
Si
a==b
, entonces ambos son verdaderos o ambos son falsos. Si ambos son verdaderos, hemos encontrado nuestros dos booleanos verdaderos, y podemos devolver verdadero (al regresara
). Si ambos son falsos, no puede haber dos booleanos verdaderos, incluso sic
es verdadero, por lo que devolvemos falso (al regresara
). Esa es la(a==b) ? a
parte ¿Qué hay de: c
? Bueno, sia==b
es falso, entonces exactamente uno dea
ob
debe ser verdadero, por lo que hemos encontrado el primer booleano verdadero, y lo único que importa es sic
también es verdadero, por lo que volvemosc
como la respuesta.fuente
a
y está deb
acuerdo, tienen el voto mayoritario, así que vaya con lo que sea, de lo contrario, no están de acuerdo, asíc
es el voto decisivo"No necesita usar las formas de cortocircuito de los operadores.
return (a & b) | (b & c) | (c & a);
Esto realiza el mismo número de operaciones lógicas que su versión, sin embargo, no tiene ramificaciones.
fuente
Aquí hay un enfoque general basado en pruebas. No es tan "eficiente" como la mayoría de las soluciones ofrecidas hasta ahora, pero claro, probado, funcionando y generalizado.
fuente
Añádelo. Se llama álgebra booleana por una razón:
Si observa las tablas de verdad allí, puede ver que la multiplicación es booleana y, además, la suma es xor.
Para responder tu pregunta:
fuente
return ((a?1:0) + (b?1:0) + (c?1:0)) >= 2
.fuente
Realmente depende de lo que quieras decir con "mejorado":
Más claro?
Terser?
¿Mas general?
¿Más escalable?
¿Más rápido?
Cuál es "mejorado" depende en gran medida de la situación.
fuente
Aquí hay otra implementación usando map / reduce. Esto escala bien a miles de millones de booleanos © en un entorno distribuido. Usando MongoDB:
Crear una base
values
de datos de booleanos:Crear el mapa, reducir funciones:
Editar : Me gusta la respuesta de CurtainDog sobre que map / reduce se aplique a listas genéricas, así que aquí va una función de mapa que toma una devolución de llamada que determina si un valor debe contarse o no.
Correr mapa / reducir:
fuente
Tomando las respuestas (hasta ahora) aquí:
y ejecutarlos a través del descompilador (javap -c X> results.txt):
Puede ver que los?: Unos son ligeramente mejores que la versión arreglada de su original. El que es el mejor es el que evita la ramificación por completo. Eso es bueno desde el punto de vista de menos instrucciones (en la mayoría de los casos) y mejor para las partes de predicción de bifurcación de la CPU, ya que una suposición errónea en la predicción de bifurcación puede causar el estancamiento de la CPU.
Diría que el más eficiente es el de moonshadow en general. Utiliza la menor cantidad de instrucciones en promedio y reduce la posibilidad de que la tubería se bloquee en la CPU.
Para estar 100% seguro, necesitaría averiguar el costo (en ciclos de CPU) para cada instrucción, que, desafortunadamente, no está disponible fácilmente (tendría que buscar la fuente del punto de acceso y luego las especificaciones de los proveedores de CPU para el momento tomado para cada instrucción generada).
Vea la respuesta actualizada de Rotsor para un análisis en tiempo de ejecución del código.
fuente
Otro ejemplo de código directo:
No es el código más sucinto, obviamente.
Apéndice
Otra versión (ligeramente optimizada) de esto:
Esto podría ejecutarse un poco más rápido, suponiendo que la comparación contra 0 usará un código más rápido (o quizás menos) que la comparación contra 2.
fuente
++n
es más rápido quen++
porque tiene que crear otra copia antes de hacer el incremento .n
anteriores), cualquier compilador decente compilará cada++
operación en una sola instrucción de CPU, ya sea pre o post.Otra forma de hacerlo, pero no muy buena:
Los
Boolean
valores del código hash se fijan en 1231 para verdadero y 1237 para falso, por lo que igualmente podría haber utilizado<= 3699
fuente
Las mejoras más obvias son:
y entonces
Pero esas mejoras son menores.
fuente
No me gusta el ternario (
return a ? (b || c) : (b && c);
de la respuesta principal), y no creo haber visto a nadie mencionarlo. Está escrito así:fuente
En Clojure :
Uso:
fuente
No creo haber visto esta solución todavía:
Su ventaja es que una vez que alcanza el número que está buscando, se rompe. Entonces, si esto fue "al menos 2 de estos 1,000,000 de valores son verdaderos" donde los dos primeros son verdaderos, entonces debería ser más rápido que algunas de las soluciones más "normales".
fuente
boolean ... boolValues
, es más fácil llamar, pero aún así toma una matrizPodemos convertir los bools a enteros y realizar esta comprobación fácil:
fuente
Como no se especificó cómo se debe mejorar el código, me esforzaré por mejorarlo haciéndolo más divertido. Aquí está mi solución:
En caso de que alguien se pregunte si este código funciona, aquí hay una simplificación que usa la misma lógica:
}
Esto se puede reducir a lo siguiente:
Pero ahora ya no es gracioso.
fuente
Demasiadas maneras de hacer esto ...
fuente
Solución de corriente alterna.
o puede preferir:
fuente
fuente
La forma más simple (IMO) que no es confusa y fácil de leer:
fuente
(C && (A || B)) || (A && B)
Acaba de cambiar los nombres * variable` ...Una interpretación literal funcionará en todos los idiomas principales:
Pero probablemente haría más fácil la lectura de las personas, y ampliable a más de tres, algo que parece ser olvidado por muchos programadores:
fuente
Como una adición a la excelente publicación de @TofuBeer TofuBeer, considere la respuesta de @pdox pdox:
Considere también su versión desmontada como la dada por "javap -c":
La respuesta de pdox se compila con menos código de byte que cualquiera de las respuestas anteriores. ¿Cómo se compara su tiempo de ejecución con los demás?
Al menos en mi computadora, la respuesta de pdox es solo un poco más rápida que la respuesta de @moonshadow moonshadow, lo que hace que pdox sea la más rápida en general (en mi computadora portátil HP / Intel).
fuente
En rubí:
[a, b, c].count { |x| x } >= 2
Que podría ejecutarse en JRuby en JavaVM. ;-)
fuente
Probablemente no esté buscando nada complicado como operadores de comparación bit a bit (normalmente no es complicado pero con booleanos, es extremadamente extraño usar operadores bit a bit) o algo que sea muy indirecto como convertir a int y resumirlos.
La forma más directa y natural de resolver esto es con una expresión como esta:
Póngalo en una función si lo prefiere, pero no es muy complicado. La solución es lógicamente concisa y eficiente.
fuente
C ª:
fuente