Java >> Java tutorial >  >> Tag >> boolean

Tjek, om mindst to ud af tre booleanere er sande i Java

1. Oversigt

boolesk er en af ​​Javas primitiver. Det er en ret ligetil datatype med kun to værdier:sand og falsk .

I denne øvelse vil vi se på et problem:at kontrollere, om der er mindst to sande i de givne tre boolean s.

2. Introduktion til problemet

Problemet er ret ligetil. Vi får tre booleans . Hvis mindst to af dem er sande , skulle vores metode returnere true .

At løse problemet er ikke en udfordring for os. Men i denne vejledning vil vi udforske et par gode løsninger. Yderligere vil vi diskutere, om hver tilgang let kan udvides til at løse et generelt problem:givet n booleans, tjek om mindst x fra dem er sande .

Vi vil verificere hver tilgang ved enhedstest. Lad os derfor først oprette et Kort genstand for at afholde testcases og de forventede resultater:

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

Som koden ovenfor viser, er TEST_CASES_AND_EXPECTED kortet indeholder fire scenarier og deres forventede resultater. Senere gennemgår vi dette kortobjekt og passerer hver boolean array som parameter for hver tilgang og kontroller, om metoden returnerer den forventede værdi.

Lad os derefter se, hvordan du løser problemet.

3. Looping gennem de tre booleanere

Den mest ligetil ide til at løse problemet kunne være at gå gennem de tre givne booleaner og tælle sandt .

Vi stopper kontrollen og returnerer true når tælleren er større end eller lig med 2 . Ellers er antallet af trues i de tre booleanere er mindre end 2. Derfor returnerer vi falsk :

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

Lad os derefter bruge vores TEST_CASES_AND_EXPECTED kort for at teste, om denne metode virker:

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

Hvis vi kører denne test, vil den ikke overraskende bestå.

Denne tilgang er ret nem at forstå. Antag yderligere, at vi ændrer metodens argument til en boolesk array (eller en samling ) og et int x . I så fald kan det nemt udvides til at blive en generisk løsning til at løse problemet:givet n booleans, tjek om mindst x af dem er sande :

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. Konvertering af Boolean til tal

På samme måde kan vi konvertere de tre booleaner til tal og beregne deres sum og kontrollere, om det er 2 eller større :

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

Lad os udføre testen for at sikre, at den fungerer som forventet:

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

Vi kan også gøre denne tilgang til en generel løsning for at kontrollere mindst x sande fra n booleans :

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

Vi har brugt Stream API til at konvertere hver boolean ind i en int og beregn summen i koden ovenfor.

5. Brug af logiske operatører

Vi har løst problemet ved at konvertere booleaner til heltal. Alternativt kan vi bruge logiske operationer til at bestemme, om mindst to af tre booleaner er sande.

Vi kan udføre det logiske OG (&& ) drift på hver anden boolean. Så vi laver tre AND-operationer på de givne tre booleaner. Hvis to af tre booleaner er sande , så skal mindst én logisk OG-operation resultere i sand :

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

Dernæst, hvis vi tester denne metode ved hjælp af TEST_CASES_AND_EXPECTED kort, det passerer også:

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

Lad os nu overveje, om vi kan udvide denne tilgang til den generelle sag. Det virker kun, når x er 2. Også, hvis n er stor nok, skal vi muligvis bygge en lang logisk operationskæde .

Derfor er det ikke egnet til et generelt problem.

6. Brug af Karnaugh-kortet

Karnaugh Map er en metode til at forenkle booleske algebraudtryk . Vi kan også skrive udtrykket fra et Karnaugh-kort. Derfor kan det nogle gange hjælpe os med at løse komplekse booleske algebraproblemer.

Lad os derefter se, hvordan du løser dette problem ved hjælp af Karnaugh-kortet. Da vi har tre booleaner, A, B og C, kan vi bygge et Karnaugh-kort:

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

I tabellen ovenfor angiver A, B og C deres sande værdier. Modsat betyder !A, !B og !C deres falske værdier.

Så, som vi har set, dækker tabellen alle mulige kombinationer af de givne tre booleaner. Desuden kan vi finde alle kombinationstilfælde, hvor mindst to booleaner er sande. For disse tilfælde har vi skrevet '1' til tabellen. Derfor er der to grupper, der indeholder dem:den første række (gruppe 1) og den første kolonne (gruppe 2).

Således ville det endelige booleske algebraudtryk, der producerer et, være:(udtrykket for at opnå alle enere i gruppe1 ) || (udtrykket for at få alle dem i gruppe2) .

Lad os derefter dele og erobre.

  • Gruppe 1 (første række) – A og B er begge sande. Uanset hvilken værdi C har, så har vi en. Derfor har vi:A &&B
  • Gruppe 2 (den første kolonne) – For det første er C altid sandt. Desuden skal der være mindst én sand i A og B. Derfor får vi:C &&(A || B)

Lad os endelig kombinere de to grupper og finde løsningen:

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

Lad os nu teste, om metoden virker som forventet:

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

Hvis vi udfører testen, består den. Det vil sige, at metoden gør arbejdet.

Men hvis vi forsøger at bruge denne metode til at løse det generelle problem, kan det være en vanskelig opgave at fremstille tabellen, når n er stor.

Derfor, selvom Karnaugh-kortet er godt til at løse komplekse boolske algebra-problemer, er det ikke egnet til nogle dynamiske og generelle opgaver .

7. Brug af xor Operatør

Lad os endelig se på en anden interessant tilgang.

I dette problem får vi tre booleaner. Yderligere har vi kendt en boolsk kan kun have to forskellige værdier:true og falsk .

Så lad os først tage to booleans fra de tre, siger a og b . Derefter kontrollerer vi resultatet af udtrykket a !=b :

  • a !=b er sandt – enten a eller b er sandt. Så hvis c er sandt, så har vi to sande. Ellers har vi to falske i de tre booleaner. Det vil sige c 's værdi er svaret.
  • a !=b er falska og b har samme værdi. Da vi kun har tre booleaner, a (eller b ) værdi er svaret.

Derfor kan vi konkludere løsningen:a !=b ? c :a . Desuden er a !=b check er faktisk en XOR-operation. Derfor kan løsningen være så enkel som:

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

Når vi tester metoden ved hjælp af TEST_CASES_AND_EXPECTED kort, vil testen bestå:

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

Denne løsning er ret kompakt og vanskelig. Men vi kan ikke udvide det til at løse det generelle problem .

8. Konklusion

I denne artikel har vi undersøgt et par forskellige tilgange til at kontrollere, om der er mindst to sande værdier i tre givne booleaner.

Desuden har vi diskuteret, hvilken tilgang der let kan udvides til at løse et mere generelt problem:Tjek, om der er mindst x sandt i n booleans.

Som altid er den komplette kildekode tilgængelig på GitHub.


Java tag