Check if at least two out of three booleans are true
Rather than writing:
if (someExpression) { return true;} else { return false;}
Write:
return someExpression;
As for the expression itself, something like this:
boolean atLeastTwo(boolean a, boolean b, boolean c) { return a ? (b || c) : (b && c);}
or this (whichever you find easier to grasp):
boolean atLeastTwo(boolean a, boolean b, boolean c) { return a && (b || c) || (b && c);}
It tests a
and b
exactly once, and c
at most once.
References
Just for the sake of using XOR to answer a relatively straight-forward problem...
return a ^ b ? c : a
Why not implement it literally? :)
(a?1:0)+(b?1:0)+(c?1:0) >= 2
In C you could just write a+b+c >= 2
(or !!a+!!b+!!c >= 2
to be very safe).
In response to TofuBeer's comparison of java bytecode, here is a simple performance test:
class Main{ static boolean majorityDEAD(boolean a,boolean b,boolean c) { return a; } static boolean majority1(boolean a,boolean b,boolean c) { return a&&b || b&&c || a&&c; } static boolean majority2(boolean a,boolean b,boolean c) { return a ? b||c : b&&c; } static boolean majority3(boolean a,boolean b,boolean c) { return a&b | b&c | c&a; } static boolean majority4(boolean a,boolean b,boolean c) { return (a?1:0)+(b?1:0)+(c?1:0) >= 2; } static int loop1(boolean[] data, int i, int sz1, int sz2) { int sum = 0; for(int j=i;j<i+sz1;j++) { for(int k=j;k<j+sz2;k++) { sum += majority1(data[i], data[j], data[k])?1:0; sum += majority1(data[i], data[k], data[j])?1:0; sum += majority1(data[j], data[k], data[i])?1:0; sum += majority1(data[j], data[i], data[k])?1:0; sum += majority1(data[k], data[i], data[j])?1:0; sum += majority1(data[k], data[j], data[i])?1:0; } } return sum; } static int loop2(boolean[] data, int i, int sz1, int sz2) { int sum = 0; for(int j=i;j<i+sz1;j++) { for(int k=j;k<j+sz2;k++) { sum += majority2(data[i], data[j], data[k])?1:0; sum += majority2(data[i], data[k], data[j])?1:0; sum += majority2(data[j], data[k], data[i])?1:0; sum += majority2(data[j], data[i], data[k])?1:0; sum += majority2(data[k], data[i], data[j])?1:0; sum += majority2(data[k], data[j], data[i])?1:0; } } return sum; } static int loop3(boolean[] data, int i, int sz1, int sz2) { int sum = 0; for(int j=i;j<i+sz1;j++) { for(int k=j;k<j+sz2;k++) { sum += majority3(data[i], data[j], data[k])?1:0; sum += majority3(data[i], data[k], data[j])?1:0; sum += majority3(data[j], data[k], data[i])?1:0; sum += majority3(data[j], data[i], data[k])?1:0; sum += majority3(data[k], data[i], data[j])?1:0; sum += majority3(data[k], data[j], data[i])?1:0; } } return sum; } static int loop4(boolean[] data, int i, int sz1, int sz2) { int sum = 0; for(int j=i;j<i+sz1;j++) { for(int k=j;k<j+sz2;k++) { sum += majority4(data[i], data[j], data[k])?1:0; sum += majority4(data[i], data[k], data[j])?1:0; sum += majority4(data[j], data[k], data[i])?1:0; sum += majority4(data[j], data[i], data[k])?1:0; sum += majority4(data[k], data[i], data[j])?1:0; sum += majority4(data[k], data[j], data[i])?1:0; } } return sum; } static int loopDEAD(boolean[] data, int i, int sz1, int sz2) { int sum = 0; for(int j=i;j<i+sz1;j++) { for(int k=j;k<j+sz2;k++) { sum += majorityDEAD(data[i], data[j], data[k])?1:0; sum += majorityDEAD(data[i], data[k], data[j])?1:0; sum += majorityDEAD(data[j], data[k], data[i])?1:0; sum += majorityDEAD(data[j], data[i], data[k])?1:0; sum += majorityDEAD(data[k], data[i], data[j])?1:0; sum += majorityDEAD(data[k], data[j], data[i])?1:0; } } return sum; } static void work() { boolean [] data = new boolean [10000]; java.util.Random r = new java.util.Random(0); for(int i=0;i<data.length;i++) data[i] = r.nextInt(2) > 0; long t0,t1,t2,t3,t4,tDEAD; int sz1 = 100; int sz2 = 100; int sum = 0; t0 = System.currentTimeMillis(); for(int i=0;i<data.length-sz1-sz2;i++) sum += loop1(data, i, sz1, sz2); t1 = System.currentTimeMillis(); for(int i=0;i<data.length-sz1-sz2;i++) sum += loop2(data, i, sz1, sz2); t2 = System.currentTimeMillis(); for(int i=0;i<data.length-sz1-sz2;i++) sum += loop3(data, i, sz1, sz2); t3 = System.currentTimeMillis(); for(int i=0;i<data.length-sz1-sz2;i++) sum += loop4(data, i, sz1, sz2); t4 = System.currentTimeMillis(); for(int i=0;i<data.length-sz1-sz2;i++) sum += loopDEAD(data, i, sz1, sz2); tDEAD = System.currentTimeMillis(); System.out.println("a&&b || b&&c || a&&c : " + (t1-t0) + " ms"); System.out.println(" a ? b||c : b&&c : " + (t2-t1) + " ms"); System.out.println(" a&b | b&c | c&a : " + (t3-t2) + " ms"); System.out.println(" a + b + c >= 2 : " + (t4-t3) + " ms"); System.out.println(" DEAD : " + (tDEAD-t4) + " ms"); System.out.println("sum: "+sum); } public static void main(String[] args) throws InterruptedException { while(true) { work(); Thread.sleep(1000); } }}
This prints the following on my machine (running Ubuntu on Intel Core 2 + sun java 1.6.0_15-b03 with HotSpot Server VM (14.1-b02, mixed mode)):
First and second iterations:
a&&b || b&&c || a&&c : 1740 ms a ? b||c : b&&c : 1690 ms a&b | b&c | c&a : 835 ms a + b + c >= 2 : 348 ms DEAD : 169 mssum: 1472612418
Later iterations:
a&&b || b&&c || a&&c : 1638 ms a ? b||c : b&&c : 1612 ms a&b | b&c | c&a : 779 ms a + b + c >= 2 : 905 ms DEAD : 221 ms
I wonder, what could java VM do that degrades performance over time for (a + b + c >= 2) case.
And here is what happens if I run java with a -client
VM switch:
a&&b || b&&c || a&&c : 4034 ms a ? b||c : b&&c : 2215 ms a&b | b&c | c&a : 1347 ms a + b + c >= 2 : 6589 ms DEAD : 1016 ms
Mystery...
And if I run it in GNU Java Interpreter, it gets almost 100 times slower, but the a&&b || b&&c || a&&c
version wins then.
Results from Tofubeer with the latest code running OS X:
a&&b || b&&c || a&&c : 1358 ms a ? b||c : b&&c : 1187 ms a&b | b&c | c&a : 410 ms a + b + c >= 2 : 602 ms DEAD : 161 ms
Results from Paul Wagland with a Mac Java 1.6.0_26-b03-383-11A511
a&&b || b&&c || a&&c : 394 ms a ? b||c : b&&c : 435 ms a&b | b&c | c&a : 420 ms a + b + c >= 2 : 640 ms a ^ b ? c : a : 571 ms a != b ? c : a : 487 ms DEAD : 170 ms