[java] 부울 3 개 중 2 개 이상이 true인지 확인

한 면접관이 최근에이 질문을했습니다. 세 개의 부울 변수 a, b 및 c가 주어지면 세 개 중 두 개 이상이 참이면 true를 반환합니다.

내 해결책은 다음과 같습니다.

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

그는 이것이 더 개선 될 수 있다고 말했다. 그러나 어떻게?



답변

쓰기보다는 :

if (someExpression) {
    return true;
} else {
    return false;
}

쓰다:

return someExpression;

표현 자체는 다음과 같습니다.

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    return a ? (b || c) : (b && c);
}

또는 이것 (쉽게 파악하기 쉬운 것) :

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    return a && (b || c) || (b && c);
}

그것은 테스트 ab정확히 한 번, 그리고 c대부분 한 번에.

참고 문헌


답변

XOR을 사용하여 비교적 간단한 문제에 대답하기 위해 …

return a ^ b ? c : a


답변

문자 그대로 구현하지 않겠습니까? 🙂

(a?1:0)+(b?1:0)+(c?1:0) >= 2

C에서는 작성 a+b+c >= 2하거나 !!a+!!b+!!c >= 2매우 안전 할 수 있습니다.

에 대한 응답으로 TofuBeer 자바 바이트 코드의 비교, 여기에 간단한 성능 테스트는 다음과 같습니다

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);
        }
    }
}

내 컴퓨터에서 다음을 인쇄합니다 (핫스팟 서버 VM (14.1-b02, 혼합 모드)으로 Intel Core 2 + sun java 1.6.0_15-b03에서 Ubuntu 실행) :

첫 번째와 두 번째 반복 :

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

나중에 반복 :

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

(a + b + c> = 2) 사례에 대해 시간이 지남에 따라 성능 을 저하시키는 Java VM의 기능은 무엇입니까 ?

그리고 -clientVM 스위치로 java를 실행하면 어떻게됩니까?

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

신비…

그리고 GNU Java Interpreter 에서 실행 하면 거의 100 배 느려지지만 a&&b || b&&c || a&&c버전이 승리합니다.

OS X를 실행하는 최신 코드를 사용한 Tofubeer의 결과 :

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

Mac Java 1.6.0_26-b03-383-11A511을 사용한 Paul Wagland의 결과

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


답변

이런 종류의 질문은 Karnaugh Map 으로 해결할 수 있습니다 .

      | C | !C
------|---|----
 A  B | 1 | 1
 A !B | 1 | 0
!A !B | 0 | 0
!A  B | 1 | 0

여기에서 첫 번째 행에 대한 그룹과 첫 번째 열에 대한 두 그룹이 필요하다고 판단하여 최적의 다유 윤활제 용액을 얻습니다.

(C && (A || B)) || (A && B)  <---- first row
       ^
       |
   first column without third case


답변

가독성이 목표가되어야합니다. 코드를 읽는 사람은 귀하의 의도를 즉시 이해해야합니다. 그래서 여기 내 해결책이 있습니다.

int howManyBooleansAreTrue =
      (a ? 1 : 0)
    + (b ? 1 : 0)
    + (c ? 1 : 0);

return howManyBooleansAreTrue >= 2;


답변

return (a==b) ? a : c;

설명:

인 경우 a==b둘 다 true이거나 둘 다 false입니다. 둘 다 true이면 두 개의 실제 부울을 찾은 후 true를 반환 할 수 있습니다 (을 반환하여 a). 둘 다 거짓이면 참인 경우에도 두 개의 참 부울이있을 수 c없으므로를 반환하여 거짓을 반환 a합니다. 그 (a==b) ? a부분입니다. 무엇에 대해 : c? 음 a==b이 거짓 이라면 , 정확히 하나 a이거나 b사실이어야합니다. 그래서 우리는 첫 번째 참 부울을 찾았습니다. 그리고 중요한 것은 남은 것이 c사실이기도합니다. 그래서 우리 c는 답으로 돌아갑니다 .


답변

단락 회로 연산자를 사용할 필요는 없습니다.

return (a & b) | (b & c) | (c & a);

이것은 버전과 동일한 수의 논리 연산을 수행하지만 완전히 분기가 없습니다.