Wednesday 5 June 2019

java - Check if at least two out of three booleans are true

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 {
for(int k=j;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 {
for(int k=j;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 {

for(int k=j;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 {
for(int k=j;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 {
for(int k=j;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[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 sum += loop1(data, i, sz1, sz2);

t1 = System.currentTimeMillis();

for(int i=0;i sum += loop2(data, i, sz1, sz2);


t2 = System.currentTimeMillis();

for(int i=0;i sum += loop3(data, i, sz1, sz2);

t3 = System.currentTimeMillis();

for(int i=0;i sum += loop4(data, i, sz1, sz2);


t4 = System.currentTimeMillis();

for(int i=0;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 ms
sum: 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

No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...