Check if at Least Two Out of Three Booleans Are True in Java – 在Java中检查三个布尔运算中是否至少有两个是真的

最后修改: 2022年 6月 10日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

boolean is one of Java’s primitives. It’s a pretty straightforward data type with only two values: true and false.

boolean是Java的primitives之一。它是一个相当直接的数据类型,只有两个值。truefalse

In this tutorial, we’ll look into a problem: checking if there are at least two true in the given three booleans.

在本教程中,我们将研究一个问题:检查给定的三个true中是否至少有两个boolean

2. Introduction to the Problem

2.对问题的介绍

The problem is pretty straightforward. We’ll be given three booleans. If at least two of them are true, our method should return true.

这个问题很简单。我们将得到三个booleans。如果其中至少有两个是true,我们的方法应该返回true

Solving the problem isn’t a challenge for us. However, in this tutorial, we’ll explore a few nice solutions. Further, we’ll discuss if each approach can be easily extended to solve a general problem: given n booleans, check if at least x from them are true.

解决这个问题对我们来说并不是一个挑战。然而,在本教程中,我们将探讨几个不错的解决方案。此外,我们将讨论每一种方法是否可以很容易地扩展到解决一般问题:给定n布尔,检查其中至少x是否为

We’ll verify each approach by unit tests. Therefore, let’s first create a Map object to hold test cases and the expected results:

我们将通过单元测试来验证每种方法。因此,让我们首先创建一个Map对象来保存测试案例和预期结果。

static final Map<boolean[], Boolean> TEST_CASES_AND_EXPECTED = ImmutableMap.of(
    new boolean[]{true, true, true}, true,
    new boolean[]{true, true, false}, true,
    new boolean[]{true, false, false}, false,
    new boolean[]{false, false, false}, false
);

As the code above shows, the TEST_CASES_AND_EXPECTED map carries four scenarios and their expected results. Later, we’ll go through this map object and pass each boolean array as the parameter to each approach and verify if the method returns the expected value.

如上面的代码所示,TEST_CASES_AND_EXPECTED地图承载了四种情况及其预期结果。稍后,我们将通过这个地图对象,将每个boolean数组作为参数传递给每个方法,并验证该方法是否返回预期值。

Next, let’s see how to solve the problem.

接下来,让我们看看如何解决这个问题。

3. Looping Through the Three Booleans

3.通过三个布尔运算的循环

The most straightforward idea to solve the problem could be walking through the three given booleans and counting trues.

解决这个问题的最直接的想法可能是走过三个给定的布尔运算并计算trues

We stop the checking and return true once the counter is greater than or equal to 2. Otherwise, the number of trues in the three booleans is less than 2. Thus, we return false:

一旦计数器大于或等于2,我们停止检查并返回true。否则,三个booleans中的trues的数量少于2,因此,我们返回false

public static boolean twoOrMoreAreTrueByLoop(boolean a, boolean b, boolean c) {
    int count = 0;
    for (boolean i : new Boolean[] { a, b, c }) {
        count += i ? 1 : 0;
        if (count >= 2) {
            return true;
        }
    }
    return false;
}

Next, let’s use our TEST_CASES_AND_EXPECTED map to test if this method works:

接下来,让我们使用我们的TEST_CASES_AND_EXPECTED地图来测试这个方法是否有效。

TEST_CASES_AND_EXPECTED.forEach((array, expected) -> 
  assertThat(ThreeBooleans.twoOrMoreAreTrueByLoop(array[0], array[1], array[2])).isEqualTo(expected));

If we run this test, unsurprisingly, it passes.

如果我们运行这个测试,不出所料,它通过了。

This approach is pretty easy to understand. Further, suppose we change the method’s argument to a boolean array (or a Collection) and an int x. In that case, it can be easily extended to become a generic solution to solving the problem: given n booleans, check if at least x of them are true:

这种方法是很容易理解的。此外,假设我们将该方法的参数改为一个boolean数组(或一个Collection)和一个int x。在这种情况下,它可以很容易地扩展为解决这个问题的通用方案:给定n个布尔值,检查其中是否至少有x

public static boolean xOrMoreAreTrueByLoop(boolean[] booleans, int x) {
    int count = 0;
    for (boolean i : booleans) { 
        count += i ? 1 : 0;
        if (count >= x) {
            return true;
        }
    }
    return false;
}

4. Converting Booleans Into Numbers

4.将布尔运算转换为数字

Similarly, we can convert the three booleans into numbers and calculate their sum and check if it’s 2 or greater:

同样地,我们可以将这三个布尔运算转换为数字,并计算它们的总和,检查是否2或更大

public static boolean twoOrMoreAreTrueBySum(boolean a, boolean b, boolean c) {
    return (a ? 1 : 0) + (b ? 1 : 0) + (c ? 1 : 0) >= 2;
}

Let’s execute the test to make sure it works as expected:

让我们执行测试,确保它按预期工作。

TEST_CASES_AND_EXPECTED.forEach((array, expected) -> 
  assertThat(ThreeBooleans.twoOrMoreAreTrueBySum(array[0], array[1], array[2])).isEqualTo(expected));

We can also turn this approach into a general solution to check at least x trues from n booleans:

我们也可以将这种方法转化为一般的解决方案,从n个布尔运算中至少检查出x个真值

public static boolean xOrMoreAreTrueBySum(Boolean[] booleans, int x) {
    return Arrays.stream(booleans)
      .mapToInt(b -> Boolean.TRUE.equals(b) ? 1 : 0)
      .sum() >= x;
}

We’ve used the Stream API to convert each boolean into an int and calculate the sum in the code above.

我们使用Stream API将每个boolean转换成int,并在上面的代码中计算出总和。

5. Using Logical Operators

5.使用逻辑运算符

We’ve solved the problem by converting booleans into integers. Alternatively, we can use logical operations to determine if at least two of three booleans are true.

我们已经通过将布尔运算转换为整数来解决这个问题了。另外,我们可以使用逻辑运算来确定三个布尔运算中是否至少有两个是真。

We can perform the logical AND (&&) operation on every two booleans. So, we’ll do three AND operations on the given three booleans. If two of three booleans are true, then at least one logical AND operation should result in true:

我们可以对每两个布尔运算进行逻辑AND(&&)操作。因此,我们将对给定的三个布尔运算进行三次AND操作。如果三个布尔运算中有两个是,那么至少有一个逻辑AND运算的结果应该是

public static boolean twoOrMoreAreTrueByOpeators(boolean a, boolean b, boolean c) {
    return (a && b) || (a && c) || (b && c);
}

Next, if we test this method using the TEST_CASES_AND_EXPECTED map, it passes, too:

接下来,如果我们使用TEST_CASES_AND_EXPECTED地图测试这个方法,它也会通过。

TEST_CASES_AND_EXPECTED.forEach((array, expected) -> 
  assertThat(ThreeBooleans.twoOrMoreAreTrueByOpeators(array[0], array[1], array[2])).isEqualTo(expected));

Now, let’s think about if we can extend this approach to the general case. It works only when x is 2. Also, if the n is large enough, we may need to build a long logical operation chain.

现在,让我们思考一下,我们是否可以将这种方法扩展到一般情况下。只有当x为2时才有效。另外,如果n足够大,我们可能需要建立一个长的逻辑运算链

Therefore, it’s not suitable for a general problem.

因此,它不适合用于一般问题。

6. Using the Karnaugh Map

6.使用卡诺地图

Karnaugh Map is a method of simplifying boolean algebra expressions. Also, we can write the expression from a Karnaugh Map. Therefore, sometimes, it can help us solve complex boolean algebra problems.

Karnaugh Map是一种简化boolean algebra表达的方法。同时,我们可以从Karnaugh Map中写出表达式。因此,有时候,它可以帮助我们解决复杂的布尔代数问题。

Next, let’s see how to solve this problem using the Karnaugh Map. Given that we have three booleans, A, B, and C, we can build a Karnaugh Map:

接下来,让我们看看如何使用卡尔纳夫图来解决这个问题。鉴于我们有三个布尔运算,A、B和C,我们可以建立一个卡尔纳夫图。

      | C | !C
------|---|----
 A  B | 1 | 1 
 A !B | 1 | 0
!A !B | 0 | 0
!A  B | 1 | 0

In the table above, A, B, and C indicate their true values. Oppositely, !A, !B, and !C mean their false values.

在上表中,A、B和C表示其值。反之,!A、!B和!C表示它们的值。

So, as we’ve seen, the table covers all possible combinations of the given three booleans. Moreover, we can find all combination cases in which at least two booleans are true. For these cases, we’ve written ‘1′ to the table. Therefore, there are two groups containing the ones: the first row (group 1) and the first column (group 2).

因此,正如我们所看到的,该表涵盖了给定的三个布尔运算的所有可能组合。此外,我们可以找到所有的组合情况,其中至少有两个布尔运算是真的。对于这些情况,我们在表中写上’1’。因此,有两组包含了1:第一行(第1组)和第一列(第2组)。

Thus, the final boolean algebra expression to produce one would be: (the expression to obtain all ones in group1 ) || (the expression to obtain all ones in group2)

因此,产生一个的最终布尔代数表达式将是。(获得第一组中所有1的表达式)||(获得第二组中所有1的表达式)

Next, let’s divide and conquer.

接下来,让我们分而治之。

  • Group 1 (the first row) – A and B are both true. No matter what value C has, we’ll have one. Therefore, we have: A && B
  • Group 2 (the first column) – First, C is always true. Moreover, there must be at least one true in A and B. Therefore, we get: C && (A || B)

Finally, let’s combine the two groups and get the solution:

最后,让我们把这两组结合起来,得到解决方案。

public static boolean twoorMoreAreTrueByKarnaughMap(boolean a, boolean b, boolean c) {
    return (c && (a || b)) || (a && b);
}

Now, let’s test if the method works as expected:

现在,让我们测试一下这个方法是否如预期的那样工作。

TEST_CASES_AND_EXPECTED.forEach((array, expected) -> 
  assertThat(ThreeBooleans.twoorMoreAreTrueByKarnaughMap(array[0], array[1], array[2])).isEqualTo(expected));

If we execute the test, it passes. That is to say, the method does the job.

如果我们执行这个测试,它就会通过。也就是说,该方法完成了工作。

However, if we try to use this method to solve the general problem, it could be a difficult job to produce the table when n is large.

然而,如果我们试图用这种方法来解决一般的问题,当n很大时,产生表格可能是一项困难的工作。

Therefore, even though the Karnaugh Map is good at solving complex boolean algebra problems, it’s not suitable for some dynamic and general tasks.

因此,尽管卡诺图擅长解决复杂的布尔代数问题,但它并不适合一些动态和一般任务

7. Using the xor Operator

7.使用xor运算符

Finally, let’s have a look at another interesting approach.

最后,让我们来看看另一种有趣的方法。

In this problem, we’re given three booleans. Further, we’ve known a boolean can only have two different values: true and false.

在这个问题中,我们得到了三个布尔运算法则。此外,我们已经知道一个boolean只能有两个不同的值。truefalse

So, let’s first take any two booleans from the three, say a and b. Then, we check the result of the expression a != b:

因此,让我们首先从三个布尔中任选两个,比如ab。然后,我们检查表达式a != b的结果。

  • a != b is true – either a or b is true. So, if c is true, then we have two trues. Otherwise, we have two false in the three booleans. That is to say, c‘s value is the answer.
  • a != b is falsea and b have the same value. Since we have only three booleans, a (or b) value is the answer.

Therefore, we can conclude the solution: a != b ? c : a. Moreover, the a != b check is actually an XOR operation. Hence, the solution can be as simple as:

因此,我们可以总结出解决方案。a != b ? c : a。此外,a != b检查实际上是一个XOR操作。因此,解决方案可以简单到。

public static boolean twoOrMoreAreTrueByXor(boolean a, boolean b, boolean c) {
    return a ^ b ? c : a;
}

When we test the method using the TEST_CASES_AND_EXPECTED map, the test will pass:

当我们使用TEST_CASES_AND_EXPECTED地图测试该方法时,测试将通过。

TEST_CASES_AND_EXPECTED.forEach((array, expected) -> 
  assertThat(ThreeBooleans.twoOrMoreAreTrueByXor(array[0], array[1], array[2])).isEqualTo(expected));

This solution is pretty compact and tricky. However, we cannot extend it to solve the general problem.

这个解决方案是相当紧凑和棘手的。然而,我们无法扩展它来解决一般问题

8. Conclusion

8.结语

In this article, we’ve explored a few different approaches to check if there are at least two trues in three given booleans.

在这篇文章中,我们探讨了几种不同的方法来检查三个给定的布尔运算中是否至少有两个真值。

Moreover, we’ve discussed which approach can be easily extended to solve a more general problem: check if there are at least x trues in n booleans.

此外,我们还讨论了哪种方法可以很容易地扩展到解决一个更普遍的问题:检查在n个布尔运算中是否至少有x个真值。

As always, the complete source code is available over on GitHub.

一如既往,完整的源代码可在GitHub上获得