Check if at least two out of three booleans are true

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 follows:

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    if ((a && b) || (b && c) || (a && c)) {
        return true;
    }
    else{
        return false;
    }
}

He said that this can be improved further, but how?


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

  • JLS 15.25 Conditional Operator ? :

  • 只是为了使用异或来回答一个相对直接的问题...

    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 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 a&&b || b&&c || a&&c 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
    
    链接地址: http://www.djcxy.com/p/40238.html

    上一篇: 在Java中将boolean转换为int

    下一篇: 检查三个布尔中至少有两个是否为真