6

Проверьте, истинны ли как минимум два из трех булевых значений

14

Недавно на собеседовании мне задали следующий вопрос: с учетом трех булевых переменных 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 ответ(ов)

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;
}

Это сделает ваш код более читабельным и понятным для большинства разработчиков.

1

Давайте разберём данный код:

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 в качестве ответа.

1

Читаемость кода — это важная цель. Человек, читающий ваш код, должен сразу понять вашу намерение. Вот моё решение:

int howManyBooleansAreTrue =
      (a ? 1 : 0)
    + (b ? 1 : 0)
    + (c ? 1 : 0);

return howManyBooleansAreTrue >= 2;

В этом коде мы используем тернарный оператор для вычисления количества истинных значений среди переменных a, b и c. Если количество истинных значений равно или превышает 2, то функция вернет true. Такой способ обеспечивает понятность и легкость восприятия логики.

0

Вам не обязательно использовать короткие формы операторов.

return (a & b) | (b & c) | (c & a);

Этот код выполняет такое же количество логических операций, как и ваша версия, но полностью без ветвлений.

0

Вот общее решение с тестированием, которое не так "эффективно", как многие предложенные ранее решения, но зато ясное, протестированное, рабочее и универсальное.

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, что делает код более читаемым и проверяемым. Тесты охватывают все возможные комбинации входных данных, что обеспечивает надежность решения.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь