An interviewer recently asked me this question: given three boolean variables, a, b, and c, return true if at least two out of the three are true.
My solution follow
He's probably not looking for anything convoluted like bitwise comparison operators (not normally convoluted but with booleans, it's extremely odd to use bitwise operators) or something that is very roundabout like converting to int and summing them up.
The most direct and natural way to solve this is with an expression like this:
a ? (b || c): (b && c)
Put it in a function if you prefer, but it's not very complicated. The solution is logically concise and efficient.
A literal interpretation will work in all major languages:
return (a ? 1:0) + (b ? 1:0) + (c ? 1:0) >= 2;
But I would probably make it easier for people to read, and expandable to more than three - something that seems to be forgotten by many programmers:
boolean testBooleans(Array bools)
{
int minTrue = ceil(bools.length * .5);
int trueCount = 0;
for(int i = 0; i < bools.length; i++)
{
if(bools[i])
{
trueCount++;
}
}
return trueCount >= minTrue;
}
A C solution.
int two(int a, int b, int c) {
return !a + !b + !c < 2;
}
or you may prefer:
int two(int a, int b, int c) {
return !!a + !!b + !!c >= 2;
}
It really depends what you mean by "improved":
Clearer?
boolean twoOrMoreAreTrue(boolean a, boolean b, boolean c)
{
return (a && b) || (a && c) || (b && c);
}
Terser?
boolean moreThanTwo(boolean a, boolean b, boolean c)
{
return a == b ? a : c;
}
More general?
boolean moreThanXTrue(int x, boolean[] bs)
{
int count = 0;
for(boolean b : bs)
{
count += b ? 1 : 0;
if(count > x) return true;
}
return false;
}
More scalable?
boolean moreThanXTrue(int x, boolean[] bs)
{
int count = 0;
for(int i < 0; i < bs.length; i++)
{
count += bs[i] ? 1 : 0;
if(count > x) return true;
int needed = x - count;
int remaining = bs.length - i;
if(needed >= remaining) return false;
}
return false;
}
Faster?
// Only profiling can answer this.
Which one is "improved" depends heavily on the situation.
Yet another way to do this but not a very good one:
return (Boolean.valueOf(a).hashCode() + Boolean.valueOf(b).hashCode() + Boolean.valueOf(c).hashCode()) < 3705);
The Boolean
hashcode values are fixed at 1231 for true and 1237 for false so could equally have used <= 3699
In Ruby:
[a, b, c].count { |x| x } >= 2
Which could be run in JRuby on the JavaVM. ;-)