2

Given the following instructions I have created a function that achieves the requirements. I feel my function is a bit too complex, though it does what it's supposed to. The difficult part for myself was avoiding the equality operators. The only way I could think to solve this is with a bit of math and a comparison operator. How can I simplify this function and save some editing time? Thanks in advance.

Write a function onlyOne that accepts three arguments of any type.

onlyOne should return true only if exactly one of the three arguments are truthy. Otherwise, it should return false.

Do not use the equality operators (== and ===) in your solution.

My function:

function onlyOne(input1, input2, input3) {
    output = false;
    let truthy = 0;
    let falsey = 0;

    if (!!input1) {
        truthy++;
    } else {
        falsey++;
    }

    if (!!input2) {
        truthy++;
    } else {
        falsey++;
    }

    if (!!input3) {
        truthy++;
    } else {
        falsey++;
    }

    if (falsey > truthy) {
        output = true;
    }
    if (falsey > 2) {
        output = false;
    }
    return output;
}
D. Seah
  • 4,472
  • 1
  • 12
  • 20
CalamityAdam
  • 354
  • 1
  • 6
  • 15

3 Answers3

4

I would call Boolean on each argument and reduce into a number, and then check the truthyness of that number minus one:

const onlyOne = (...args) => {
  const numTruthy = args.reduce((a, arg) => a + Boolean(arg), 0);
  return !Boolean(numTruthy - 1);
};
console.log(onlyOne(0, 0, 0));
console.log(onlyOne(0, 0, 1));
console.log(onlyOne(0, 1, 1));
console.log(onlyOne(1, 1, 1));

Or, for a more concise but less understandable version, you can integrate the 1 into the initial value provided to reduce:

const onlyOne = (...args) => !args.reduce((a, arg) => a + Boolean(arg), -1);

console.log(onlyOne(0, 0, 0));
console.log(onlyOne(0, 0, 1));
console.log(onlyOne(0, 1, 1));
console.log(onlyOne(1, 1, 1));
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
0

You can use filter and count as below.

In filterCount function first parameter will decide whether you want count of truthy or falsy.

const filterCount = (bool, ...args) => args.filter(i => i == bool).length;

console.log("truthy = " + filterCount(true, 1, 0, 0));
console.log("falsy = " + filterCount(false, 1, 0, 0));
console.log("truthy = " + filterCount(true, 1, 0, 1));
console.log("falsy = " + filterCount(false, 1, 0, 1));
Karan
  • 12,059
  • 3
  • 24
  • 40
0

One liner:

let onlyOne = (a, b, c) => !(!!a + !!b + !!c - 1);

!! coerces the values into booleans. + coerces the booleans into numbers, where true becomes 1 and false becomes 0. We sum up the numbers and now we can have any one of these potential totals: 0, 1, 2, or 3. We only care about a total of 1 which we can subtract 1 from to get 0 and then negate it (which coerces it back into a boolean) which makes it true.

pretzelhammer
  • 13,874
  • 15
  • 47
  • 98