Check to see if exactly two out of three booleans are true?

Viewed 3814

I need to test to see if exactly two out of three booleans are true.

Something like this:

if ((a && b && !c) || (a && !b && c) || (!a && b && c)) {
  // success
}

Is this the most direct way to go about this? Does anyone know of a shortcut/shorthand?

8 Answers

If you add the values you can check if the result is 2

if ((a + b + c) == 2) {
    // do something
}

I would go this readable (IMO) way:

let conditions = [a && b && !c, a && !b && c, !a && b && c]
if(conditions.filter(c => c).length === 2) { /* ... */}

You don't really need to even convert them.

let a = true;
let b = true;
let c = false;

if(a + b + c === 2) {
    console.log('You won!');
} else {
    console.log('Not 2');
}

You can just convert (cast) those booleans to integers and add them together. Then check if it's equal to 2. Like this (C):

int res = (int)a + (int)b + (int)c;
if (res == 2) { /* Do something... */ }

EDIT:

For JavaScript you don't even need to cast the values:

const res = a + b + c
if (res == 2) { /* Do something... */ }

If you're trying to see if exactly two out of three booleans are true multiple times, you can use a function to shorten your code.

function boolTest(a, b, c) {
    if ((a && b && !c) || (a && !b && c) || (!a && b && c)) {
        return true
    } else {
        return false
    }
}

Then, you can use it like this:

boolTest(true, true, false) // returns true
boolTest(false, true, false) // returns false

In JavaScript (and most other modern coding languages), Boolean variables can be stored as binary integers (1 and 0), and those integers can be used as Booleans. See this example:

if (1) {
    console.log("1 is true");
} else {
    console.log("1 is false");
}

if (0) {
    console.log("0 is true");
} else {
    console.log("0 is false");
}

So to do a check for two out of three Booleans, you could do this:

var a = true;
var b = false;
var c = true;

var total = (a ? 1 : 0) + (b ? 1 : 0) + (c ? 1 : 0);
if (total == 2) {
    console.log("Success!");
}

Hopefully this helps!

a=true;
b=true;
c=false;
arr = [a,b,c]
result = arr.reduce((acc, cur) => acc+cur) == 2;

console.log(result);

The advantages of this approach are:

  • no conversion to Boolean
  • easy to generalize to arrays of any size / any number of trues

For longer arrays one might consider a better performing solution that stops summing as soon as the desired number is reached

n=2
// large array
arr=[true,true,true].concat(Array(10000).fill(false))

// reduce will stop as soon as result is >n
result = arr.slice(0).reduce((acc, cur, i, a) => {acc+=cur; if (acc>n) a.splice(1); return acc});
console.log(result==2)

Related