3/4가 참인지 테스트하는 논리


163

돌아오고 싶어 True4 개의 부울 값 중 3 개가 true 인 경우에만 .

내가 얻은 가장 가까운 것은 (x ^ y) ^ (a ^ b):

어떻게해야합니까?


10
흠, 수학 공식없이 생각할 수있는 유일한 방법은 count를 사용하는 것입니다. 좋은 질문! :)
저는 Cavic

10
생각은 나쁘지 않지만 부정을 취해야 not a ^ not b ^ not c ^ not d합니다. 부정 된 값 중 하나만 참이면 참입니다. 이는 원래 값에서 정확히 하나가 거짓임을 의미합니다.
Ingo

23
이 세부 사항 의 실제 문제 는 무엇입니까 ?
Wolf

5
@Ingo not a ^ not b ^ not c ^ not d 단 하나만 거짓이고 3이 거짓이면 true를 반환합니다.
NameSpace

9
명백한 비 카운트 솔루션은 (!a&&b&&c&&d) || (a&&!b&&c&&d) || (a&&b&&!c&&d) || (a&&b&&c&&!d)입니다.
Jason C

답변:


248

의미를 나타내는 방식으로 코드를 작성하는 것이 좋습니다. 3 개의 값을 true로 원하면 3 값이 어딘가에 나타나는 것이 당연합니다.

예를 들어,에 C++:

if ((int)a + (int)b + (int)c + (int)d == 3)
    ...

이는 잘 정의되어 C++다음은 standard (§4.7/4)변환 것을 나타낸다 bool하려면 int예상 값 0 또는 1을 제공한다.

Java 및 C #에서는 다음 구성을 사용할 수 있습니다.

if ((a?1:0) + (b?1:0) + (c?1:0) + (d?1:0) == 3)
    ...

23
이것은 좋은 대답입니다. 이것은 X / Y의 경우처럼 보입니다. "그는 Y를 사용하여 X를하고 싶지만 Y를하는 방법을 모른다. X를 묻는 대신 Y에게 묻는다." 그가 논리 회로 또는 이와 유사한 것을 설계하지 않는 한 (그리고 잘못된 사이트에있을 경우), 가장 좋은 방법은 읽을 수 있는 방법입니다 .
NothingsImossible

2
@NothingsImpossible 질문에 대한 XY는 없습니다. 프로그래밍에서 일반적으로 발생하는 문제를 해결하는 데 대한 명확하고 직접적인 질문입니다. Y는 관련이 없습니다.
Ярослав Рахматуллин

감사! 이것은 실제로 내가 하려는 일이지만 내 아이디어는 너무 어색해서 부울 논리에 도달했습니다.
Simon Kuang

3
if (!!a + !!b + !!c + !!d == 3)컴파일러가 이것을 최적화하는지 아닌지는 모르겠지만 작성하기가 더 쉽다
phuclv

2
C ++에서는 bool에서 int로 캐스트 할 필요가 없습니다.
PlasmaHH

90

# 1 : 분기 사용? : 3 또는 4 작업

A ^ B ? C & D : ( C ^ D ) & A

# 2 브랜칭, 7 가지 작업

(A ^ B ^ C ^ D) & ((A & B) | (C & D))

내가 모든 것을 프로파일 링하는 데 사용했을 때 , CPU가 코드 경로를 더 잘 예측하고 더 많은 작업을 동시에 실행할 수 있기 때문에 비 분기 솔루션이 작동에 훨씬 더 빠르다는 것을 알았습니다 . 그러나 분기 성명서의 작업은 약 50 % 적습니다.


18
+1-다른 답변은 대부분의 프로그래밍 언어에 더 적합하지만 # 2는 순수한 부울 논리에서 가장 좋은 답변입니다.
Brilliand

2

68

이것이 파이썬 이었다면

if [a, b, c, d].count(True) == 3:

또는

if [a, b, c, d].count(False) == 1:

또는

if [a, b, c, d].count(False) == True:
# In Python True == 1 and False == 0

또는

print [a, b, c, d].count(0) == 1

또는

print [a, b, c, d].count(1) == 3

또는

if a + b + c + d == 3:

또는

if sum([a, b, c, d]) == 3:

부울은 파이썬에서 정수의 서브 클래스이기 때문에이 모든 것이 작동합니다.

if len(filter(bool, [a, b, c, d])) == 3:

또는이 깔끔한 트릭 에서 영감을 얻은

data = iter([a, b, c, d])
if not all(data) and all(data):

17
+1 이것은 문제를 파이썬으로 올바르게 번역함으로써 문제를 해결합니다.
Wolf

사람들이 파이썬의 부울 컨텍스트에서 0이 아닌 정수를 반환 할 수 있기 때문에 이것은 약간 위험합니다. 오래된 C 트릭은 파이썬에서도 작동합니다 a=5;not not a == 1. 실제 부울 유형이 없다는 단점이 있습니다.
Voo

@Voo 우리는 또한이 bool:)
thefourtheye

@thefourtheye 아 네, 이중 부정 트릭 / 해킹보다 훨씬 좋습니다.
Voo

1
아니면 ... 또는 ... 또는 .... 한 가지 분명한 방법이 있어야합니다. :-/ :-)
rz.

53

길지만 매우 단순하고 (분리형) 일반 형태 :

 (~a & b & c & d) | (a & ~b & c & d) | (a & b & ~c & d) | (a & b & c & ~d)

간단하지만 더 많은 생각이 필요합니다 : P


2
@Ben은 다양한 일반 형태를 제공합니다. 이것은 이미 (DNF)에 있습니다.
Riking

8
어때요 (a & b & (c ^ d)) | ((a ^ b) & c & d)?
user253751

2
예, @immibis, Wolfram Alpha에 따르면 DNF는 내가 작성한 공식이므로 동일한 부울 함수입니다.
Gastón Bengolea

2
+1 코드를 읽는 사람이 다른 답변보다 더 빨리 시도되는 것을 이해할 것이라고 생각하기 때문에 +1.
Boluc Papuccuoglu


22

이 논리를 프로그래밍 언어로 사용하려면 제 제안은

bool test(bool a, bool b, bool c, bool d){
    int n1 = a ? 1 : 0;
    int n2 = b ? 1 : 0;
    int n3 = c ? 1 : 0;
    int n4 = d ? 1 : 0;

    return n1 + n2 + n3 + n4 == 3;
}

또는 원하는 경우 다음을 모두 한 줄에 넣을 수 있습니다.

return (a ? 1 : 0) + (b ? 1 : 0) + (C ? 1 : 0) + (d ? 1 : 0) == 3;

또한이 문제를 n of m 다음과 같이 일반화 할 수 있습니다 .

bool test(bool *values, int n, int m){
    int sum = 0;
    for(int i = 0; i < m; i += 1){
        sum += values[i] ? 1 : 0;
    }
    return sum == n;
}

12
나를 이길. 가독성은 항상 영리함을 능가합니다. +1
MikeTheLiar

20

이 답변은 표현 시스템에 따라 다르지만 0이 false로 해석되는 유일한 값이고 not(false)항상 같은 숫자 값을 반환 not(a) + not(b) + not(c) + not(d) = not(0)하면 트릭을 수행해야합니다.


18

단지 논리적 문제가 아닌 프로그래밍 질문에 대한 답은 프로그래밍 언어의 선택에 달려 있음을 명심하십시오. 일부 언어는 다른 언어와 다른 기능을 지원합니다.

예를 들어 C ++에서는 다음을 사용하여 조건을 테스트 할 수 있습니다.

(a + b + c + d) == 3

부울에서 정수 유형으로의 자동 (낮은 수준) 변환을 지원하는 언어에서 확인하는 가장 빠른 방법입니다. 그러나 그 문제에 대한 일반적인 대답은 없습니다.


2
이것이 내가 게시 할 답변입니다. 사용되는 프로그래밍 언어에 따라 추가해야 할 한 가지는 -3입니다. VB에서 True = -1입니다.
Tom Collins


11
((a xor b) xor (c xor d)) and ((a or b) and (c or d))

주먹 표현 true은 4 에서 1 또는 3을 검색합니다 . 두 번째 표현 은 4에서 0 또는 1 (때로는 2)을 제거 true합니다.


11

Java 8에서 잘못된 값을 필터링하고 나머지 실제 값을 계산하십시오.

public static long count(Boolean... values) {
    return Arrays.stream(values).filter(t -> t).count();
}

그런 다음 다음과 같이 사용할 수 있습니다.

if (3 == count(a, b, c, d)) {
    System.out.println("There... are... THREE... lights!");
}

쉽게 확인에 일반화 nm항목이 진실되고.


11

적어도 n모두 를 확인하려면 Boolean(n은 총 수보다 작거나 같아야 함 Boolean: p)

if (((a ? 1:0) + (b ? 1:0 ) + (c ? 1:0) + (d ? 1:0 )) >= n) {
    // do the rest
}

편집 : @ Cruncher의 의견 후

boolean4 개 중 3 개 를 확인하려면

if (((a ? 1:0) + (b ? 1:0 ) + (c ? 1:0) + (d ? 1:0 )) == 3) {
    // do the rest
}

다른 것 :

((c & d) & (a ^ b)) | ((a & b) & (c ^ d))( 세부 사항 )


OP는 적어도 n이 아닌 정확히 n을 원합니다. 그러나 이것은이 솔루션에서 쉽게 변경됩니다
Cruncher

2
@Wolf 그 질문은 StackUnderflow.com에 속합니다 : p
버그 아님

10

LINQ를 사용하여 C #에서 해결할 수있는 방법은 다음과 같습니다.

bool threeTrue = new[] { a, b, x, y }.Count(x => x) == 3;

10

이것이 대칭형 부울 함수 S₃(4)입니다. 대칭 부울 함수는 설정된 입력 수에만 의존하지만 입력에 의존하지 않는 부울 함수입니다. Knuth는 컴퓨터 프로그래밍 기술 4 권 섹션 7.1.2에서이 유형의 기능을 언급합니다.

S₃(4) 다음과 같이 7 가지 연산으로 계산할 수 있습니다.

(x && y && (a || b)) ^ ((x || y) && a && b)

크 누스이 당신이 정상 연산자를 사용하여보다 7 작업에서이 작업을 수행 할 수 있음을 의미 최적임을 보여줍니다 : &&, || , ^, <,>.

그러나 1true와 0false 를 사용하는 언어로 이것을 사용 하려면 쉽게 추가를 사용할 수 있습니다.

x + y + a + b == 3

그것은 당신의 의도를 아주 분명하게 만듭니다.


9
(a && b && (c xor d)) || (c && d && (a xor b))

순수한 논리 관점에서 이것은 내가 생각해 낸 것입니다.

비둘기 구멍 원리에 따르면 정확히 3이 참이면 a와 b가 참이거나 c와 d가 참입니다. 그런 다음 각 사례를 정확히 다른 하나와 함께 처리하는 문제입니다.

볼프람 진리표


이것은 네임 스페이스의 두 번째 솔루션과 같습니다.
Brilliand

@Brilliand 나와 다른 것 같습니다. 그의 xors는 모두 3 또는 1을 모두 얻기 위해 함께 모여 2 개의 별개의 그룹 중 하나 이상을 요구하여 1을 가진 것을 제외합니다. (1 또는 3과 2 이상으로 요약). 광산에는 별개의 그룹 중 하나와 다른 그룹 중 하나가 필요합니다.
Cruncher

당신이 그 의미에서 동등한 것을 의미한다면 mine <=> his, 이것이 예상 되는대로 무엇을 말 해야할지 모르겠습니다.
Cruncher

나는 NameSpace의 (이전) 답변에서 다루지 않은 새로운 것을 추가하지 않고 NameSpace의 두 번째 솔루션과 동일한 방식 으로이 답변이 훌륭하다는 것을 의미한다고 생각합니다. 글쎄, 난 어쨌든 upvote거야.
Brilliand

8

Karnaugh Maps와 같은 논리 시각화 도구를 사용하는 경우 이는 하나의 if (...) 행에 쓰려고한다면 완전한 논리 용어를 피할 수없는 문제입니다. Lopina는 이미 그것을 보여주었습니다. 더 간단하게 작성할 수는 없습니다. 비트를 제외 할 수는 있지만 기계를 읽기 어렵습니다.

계산 솔루션은 나쁘지 않으며 실제로 당신이 무엇을하는지 보여줍니다. 계산을 효율적으로 수행하는 방법은 프로그래밍 언어에 따라 다릅니다. Python 또는 LinQ를 사용한 배열 솔루션은보기에 좋지만 조심하십시오. Wolf 's (a + b + x + y) == 3는 훌륭하고 빠르게 작동하지만 언어가 "true"와 1과 같은 경우에만 해당합니다. "true"가 -1로 표시되면 -3을 테스트해야합니다. )

귀하의 언어가 진정한 부울을 사용한다면, 명시 적으로 프로그래밍을 시도 할 수 있습니다 (나는 XOR 테스트로! =를 사용합니다)

if (a)
{
    if (b)
        return (x != y);    // a,b=true, so either x or y must be true
    else
        return (x && y);     // a=true, b=false, so x AND y must be true
}
else
{
    if (b)
        return (x && y);    // a=false, b=true, so x and y must be true
    else
        return false;       // a,b false, can't get 3 of 4
}

"x! = y"는 x, y가 부울 유형 인 경우에만 작동합니다. 그것들이 0이고 다른 모든 것이 참인 다른 유형이라면 실패 할 수 있습니다. 그런 다음 부울 XOR 또는 ((bool) x! = (bool) y)를 사용하거나 "if (x) return (y == false) else return (y == true);"를 쓰십시오. 컴퓨터를 위해 일하십시오.

프로그래밍 언어가 삼항? : 연산자를 제공하면 다음과 같이 단축 할 수 있습니다.

if (a)
    return b ? (x != y) : (x && y);
else
    return b ? (x && y) : false;

약간의 가독성을 유지하거나 적극적으로

return a ? (b ? (x != y) : (x && y)) : (b ? (x && y) : false);

이 코드는 정확히 세 가지 논리 테스트 (상태 a, 상태 b, x와 y의 비교)를 수행하며 여기에있는 대부분의 다른 답변보다 빠릅니다. 그러나 당신은 그것을 언급해야합니다, 그렇지 않으면 3 개월 후에 그것을 이해하지 못할 것입니다 :)


8

여기에는 좋은 답변이 많이 있습니다. 다음은 아직 아무도 게시하지 않은 대체 공식입니다.

 a ? (b ? (c ^ d) : (c && d)) : (b && c && d)

답변 해 주셔서 감사합니다. 어떻게 작동하는지에 대한 설명을 추가해 주시겠습니까? 감사.
Deanna

(죄송합니다. 검토 감사로 받았습니다. 적어도 통과했습니다. : :))
Deanna

7

첫 번째 답변과 비슷하지만 순수한 Java :

int t(boolean b) {
    return (b) ? 1 : 0;
}

if (t(x) + t(y) + t(a) + t(b) == 3) return true;
return false;

더 읽기 쉬운 코드를 만들기 때문에 정수로 계산하는 것을 선호합니다.


7

에서 파이썬 , 요소의 반복자의 얼마나 많은을 볼 수있는 사실, 사용 sum(그것은 아주 간단합니다)

설정

import itertools

arrays = list(itertools.product(*[[True, False]]*4))

실제 시험

for array in arrays:
    print(array, sum(array)==3)

산출

(True, True, True, True) False
(True, True, True, False) True
(True, True, False, True) True
(True, True, False, False) False
(True, False, True, True) True
(True, False, True, False) False
(True, False, False, True) False
(True, False, False, False) False
(False, True, True, True) True
(False, True, True, False) False
(False, True, False, True) False
(False, True, False, False) False
(False, False, True, True) False
(False, False, True, False) False
(False, False, False, True) False
(False, False, False, False) False

5

종이 (비 프로그래밍) 솔루션을 따르는 경우 K-maps 및 Quine-McCluskey 알고리즘을 사용하면 부울 함수를 최소화 할 수 있습니다.

귀하의 경우 결과는

y = (x̄3 ^ x2 ^ x1 ^ x0) ∨ (x3 ^ x̄2 ^ x1 ^ x0) ∨ (x3 ^ x2 ^ x̄1 ^ x0) ∨ (x3 ^ x2 ^ x1 ^ x̄0)

프로그래밍 방식으로 고정되지 않은 양의 변수와 사용자 정의 "임계 값"을 수행하려면 부울 값 목록을 통해 반복하고 "true"의 횟수를 계산하는 것은 매우 간단하고 간단합니다.


1
바 오버 헤드는 무엇을 의미합니까? 목록 아래로 이동하는 것을 알 수 있습니다.
네임 스페이스

3
@NameSpace 사람들이 "하지"표현하기 위해 사용하는 표기법이 너무 많은 IMO 중 하나입니다.

5

4 개 중 3 개의 부울 값이 true 인 경우에만 true를 반환하고 싶습니다.

4 개의 부울 값 a, b, x, y가 주어지면이 작업은 다음 C 문으로 변환됩니다.

return (a+b+x+y) == 3;

1
좋은 함정. 이것은 true1과 같다고 가정합니다 . 이것은 모든 언어 / 사례에서 사실이 아닙니다. blogs.msdn.com/b/oldnewthing/archive/2004/12/22/329884.aspx
JensG

@JensG 당신이 맞아요 : 나는이 가정을 명백하게합니다. Thx :)
Wolf

4
((a^b)^(x^y))&((a|b)&(x|y))

당신이 원하는 것입니다. 기본적으로 코드를 가져 와서 실제로 3이 true인지 3이 아닌지 검사를 추가했습니다.


4

재귀와 관련된 답이없는 프로그래밍 질문? 상상할 수없는!

"정확하게 3 개 중 3 개"답변이 충분하지만, 다음과 같이 할 수있는 "n 개 중 정확히 n 개"(그렇지 않으면 재귀는 실제로 가치가 없음)에 대한 일반화 된 (Java) 버전이 있습니다.

public static boolean containsTrues(boolean[] someBooleans,
    int anIndex, int truesExpected, int truesFoundSoFar) {
  if (anIndex >= someBooleans.length) {
    return truesExpected == truesFoundSoFar; // reached end
  }
  int falsesExpected = someBooleans.length - truesExpected;
  boolean currentBoolean = someBooleans[anIndex];
  int truesFound = truesFoundSoFar + (currentBoolean ? 1 : 0);
  if (truesFound > truesExpected) {
    return false;
  }
  if (anIndex - truesFound > falsesExpected) {
    return false; // too many falses
  }
  return containsTrues(someBooleans, anIndex + 1, truesExpected,
      truesFound);
}

이것은 다음과 같이 호출 될 수 있습니다.

 boolean[] booleans = { true, false, true, true, false, true, true, false };
 containsTrues(booleans, 0, 5, 0);

반환해야합니다 true(8 값 중 5 개가 예상대로 참 이었기 때문에). "trues"와 "falses"라는 단어에는 만족하지 않지만 지금은 더 나은 이름을 생각할 수 없습니다 ... 재귀는 너무 많 true 거나 너무 많은 false값이 발견 되면 중지됩니다 .


@ FélixSaparelli : "진실"이 여기에 적용되는지 확실하지 않습니다 ... 하나만 있으면 행복 할 것 같습니다 true. 아마도 같은 것 containsNumberOfTrueValues()입니다. 제쳐두고 : 스몰 토크의 이름 지정은 이것에 훨씬 더 적합 할 것입니다 : doesArray: someBooleans startingAt: anIndex containNumberOfTrueValues: anExpectedNumber foundSofar: aNumberFoundSoFar. 아마 일부 자바 개발자의 취향에 비해 너무 길지만, Smalltalkers는 적절한 이름 지정을 두려워하지 않습니다. ;-)
Amos M. Carpenter

그것은 대부분 유머였다. 그리고 containsTruth말 그대로 "알려지지 않은 양의 진실을 포함하고있다"는 뜻이므로, 나는 그것이 옳다고 믿습니다.
Félix Saparelli

3

가독성은 큰 관심사이므로 설명 함수 호출을 사용하여 제안 된 구현을 래핑 할 수 있습니다. 이 계산을 여러 위치에서 수행해야하는 경우 재사용을 달성하는 가장 좋은 방법은 함수 호출이며, 현재 수행중인 작업을 명확하게 보여줍니다.

bool exactly_three_true_from(bool cond1, bool cond2, bool cond3, bool cond4)
{
    //...
}

3

PHP에서, 더 동적으로 만들기 (조건의 수 등을 변경하는 경우를 대비하여) :

$min = 6;
$total = 10;

// create our boolean array values
$arr = array_map(function($a){return mt_rand(0,1)>0;},range(1,$total));

// the 'check'
$arrbools = array_map(function($a){return (int)$a;},$arr);
$conditionMet = array_sum($arrbools)>=$min;

echo $conditionMet ? "Passed" : "Failed";

2
(((a AND b) OR (x AND y)) AND ((a XOR b) OR (x XOR y)))

이것이 좋은 해결 책임을 보여줄 수는 있지만 Sam Hocevar의 답변은 나중에 작성하고 이해하기 쉽습니다. 내 책에서 더 좋아집니다.


1

다음은 내가 영감을 주었기 때문에 방금 작성한 C # 코드입니다.

그것은 많은 양의 논쟁을 취하고 그들 중 n이 참인지 알려줄 것입니다.

    static bool boolTester(int n, params bool[] values)
    {
        int sum = 0;           

        for (int i = 0; i < values.Length; i++)
        {
            if (values[i] == true)
            {
                sum += 1;
            }                
        }
        if( sum == n)
        {
            return true;
        }            
        return false;                
    }

그리고 당신은 그렇게 그렇게 부릅니다.

        bool a = true;
        bool b = true;
        bool c = true;
        bool d = false;            

        bool test = false;
        test = boolTester(3, a, b, c, d);

이제 원하는대로 7/9 또는 15/100을 테스트 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.