Проверьте, истинны ли как минимум два из трех булевых значений
Недавно на собеседовании мне задали следующий вопрос: с учетом трех булевых переменных a, b и c, вернуть true, если хотя бы две из трех значений истинны.
Мое решение выглядит так:
boolean atLeastTwo(boolean a, boolean b, boolean c) {
if ((a && b) || (b && c) || (a && c)) {
return true;
}
else{
return false;
}
}
Интервьюер сказал, что это решение можно улучшить, но как именно?
5 ответ(ов)
Ваш код использует оператор XOR (^) для сравнения двух значений a
и b
. В данном случае, выражение a ^ b
вернёт ненулевое значение (истина), если a
и b
различны, и ноль (ложь), если они равны. Таким образом, ваш код можно интерпретировать следующим образом:
- Если
a
иb
различны (результатa ^ b
не равен нулю), то будет возвращено значениеc
. - Если
a
иb
равны (результатa ^ b
равен нулю), вернётсяa
.
Тем не менее, такой подход с использованием XOR может быть не самым очевидным для читателей, что усложняет понимание вашей логики. Если вашей целью является простота и ясность кода, возможно, стоит рассмотреть более традиционный способ записи этого условия:
if (a != b) {
return c;
} else {
return a;
}
Это сделает ваш код более читабельным и понятным для большинства разработчиков.
Давайте разберём данный код:
return (a==b) ? a : c;
Объяснение:
Если a == b
, это означает, что оба значения либо равны true
, либо равны false
. Если оба равны true
, то мы нашли два истинных булевских значения, и можем вернуть true
, то есть вернём значение a
. Если оба равны false
, тогда не может быть двух истинных булевских значений, даже если c
равно true
, поэтому возвращаем false
, также возвращая значение a
. Это и есть часть (a == b) ? a
.
Что касается : c
, если a == b
— это false
, то точно одно из значений a
или b
должно быть истинным. Таким образом, мы находим первое истинное булевское значение. В этом случае остаётся важным только то, истинно ли c
, и мы возвращаем c
в качестве ответа.
Читаемость кода — это важная цель. Человек, читающий ваш код, должен сразу понять вашу намерение. Вот моё решение:
int howManyBooleansAreTrue =
(a ? 1 : 0)
+ (b ? 1 : 0)
+ (c ? 1 : 0);
return howManyBooleansAreTrue >= 2;
В этом коде мы используем тернарный оператор для вычисления количества истинных значений среди переменных a
, b
и c
. Если количество истинных значений равно или превышает 2, то функция вернет true
. Такой способ обеспечивает понятность и легкость восприятия логики.
Вам не обязательно использовать короткие формы операторов.
return (a & b) | (b & c) | (c & a);
Этот код выполняет такое же количество логических операций, как и ваша версия, но полностью без ветвлений.
Вот общее решение с тестированием, которое не так "эффективно", как многие предложенные ранее решения, но зато ясное, протестированное, рабочее и универсальное.
public class CountBooleansTest extends TestCase {
public void testThreeFalse() throws Exception {
assertFalse(atLeastTwoOutOfThree(false, false, false));
}
public void testThreeTrue() throws Exception {
assertTrue(atLeastTwoOutOfThree(true, true, true));
}
public void testOnes() throws Exception {
assertFalse(atLeastTwoOutOfThree(true, false, false));
assertFalse(atLeastTwoOutOfThree(false, true, false));
assertFalse(atLeastTwoOutOfThree(false, false, true));
}
public void testTwos() throws Exception {
assertTrue(atLeastTwoOutOfThree(false, true, true));
assertTrue(atLeastTwoOutOfThree(true, false, true));
assertTrue(atLeastTwoOutOfThree(true, true, false));
}
private static boolean atLeastTwoOutOfThree(boolean b, boolean c, boolean d) {
return countBooleans(b, c, d) >= 2;
}
private static int countBooleans(boolean... bs) {
int count = 0;
for (boolean b : bs)
if (b)
count++;
return count;
}
}
В этом коде реализована простая логика для проверки, есть ли как минимум два значения true
среди трех булевых переменных. Мы используем метод countBooleans
для подсчета количества значений true
и применяем этот метод в функции atLeastTwoOutOfThree
, что делает код более читаемым и проверяемым. Тесты охватывают все возможные комбинации входных данных, что обеспечивает надежность решения.
Проверьте, что строка не равна null и не пуста
Почему нет ConcurrentHashSet, если есть ConcurrentHashMap?
Как объявить массив в одну строку?
Загрузка JDK Java на Linux через wget приводит к отображению страницы лицензии вместо установки
Создание репозитория Spring без сущности