web-dev-qa-db-ja.com

4つのうち3つが真であることをテストするロジック

4つのブール値のうち3つが真である場合にのみ、Trueを返します。

一番近いのは (x ^ y) ^ (a ^ b)

私は何をすべきか?

163
Simon Kuang

意味を示す方法でコードを書くことをお勧めします。 3つの値をtrueにしたい場合、値3がどこかに表示されるのは自然なことです。

たとえば、_C++_:

_if ((int)a + (int)b + (int)c + (int)d == 3)
    ...
_

これは_C++_で明確に定義されています。standard (§4.7/4)は、boolintに変換すると期待値0または1が得られることを示します。

JavaおよびC#では、次の構成を使用できます。

_if ((a?1:0) + (b?1:0) + (c?1:0) + (d?1:0) == 3)
    ...
_
246
sam hocevar

#1:分岐の使用?:3つまたは4つの操作

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

#2非分岐、7つの操作

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

CPUがコードパスをより正確に予測し、タンデムでより多くの操作を実行できるため、すべてのプロファイルに使用するときに、 非分岐 ソリューションは操作ごとの操作がかなり高速であることがわかりました。ただし、ここでは分岐ステートメントの作業が約50%少なくなります。

89
NameSpace

これがPythonだったら、私は書いていただろう

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:

ブールはPythonの整数のサブクラスであるため、これらはすべて機能します。

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

または、これに触発された ニートトリック

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

長いが非常にシンプルな(選言的)標準形:

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

それは単純化されるかもしれませんが、それはより多くの思考を必要とします:P

52

もっと簡単かどうかはわかりませんが、多分。

((x xor y) and (a and b)) or ((x and y) and (a xor b))

33
Karl Kieninger

プログラミング言語でこのロジックを使用する場合、私の提案は

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

または、必要に応じて、これらすべてを1行に入れることができます。

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;
}
22
Hi I'm Frogatto

この答えは表現のシステムに依存しますが、0がfalseと解釈される唯一の値であり、not(false)が常に同じ数値を返す場合、not(a) + not(b) + not(c) + not(d) = not(0)はトリックを行う必要があります。

20
MattClarke

SO単なる論理的な問題ではなく、プログラミングの質問の場合、答えは明らかにプログラミング言語の選択に依存することを忘れないでください。

たとえば、C++では、次の条件を使用して条件をテストできます。

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

これは、ブール型から整数型への自動(低レベル)変換をサポートする言語でチェックを行う最速の方法です。しかし、再び、その問題に対する一般的な答えはありません。

17
GOTO 0
12
Simon Kuang

すべてのnのうち少なくともBooleanが真であることを確認するには、(nはBoolean:pの総数以下でなければなりません)

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

Edit:@Cruncherのコメントの後

4のうち3 booleanを確認するには

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))詳細

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

最初の式は、4つのうち1つまたは3つのtrueを検索します。2番目の式は、4つのうち0または1(および2つ)trueを削除します。

11
durum

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

nアイテムのmがtrueであるかどうかのチェックに簡単に一般化します。

11
David Conrad

LINQを使用してC#で解決できる方法を次に示します。

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

それは対称ブール関数S₃(4)です。対称ブール関数は、設定された入力の量にのみ依存するブール関数ですが、どの入力であるかには依存しません。 Knuthは、The Program of Computer ProgrammingのVolume 4のセクション7.1.2でこのタイプの機能に言及しています。

S₃(4)は、次の7つの操作で計算できます。

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

Knuthは、これが最適であることを示しています。つまり、通常の演算子&&, || , ^, <,>を使用して7回未満の操作でこれを行うことはできません。

ただし、1をtrueに、0をfalseに使用する言語でこれを使用する場合は、追加も簡単に使用できます。

x + y + a + b == 3

これにより、意図が明確になります。

10
Paulpro
(a && b && (c xor d)) || (c && d && (a xor b))

純粋な論理的な観点から、これは私が思いついたものです。

ハトの穴の原理により、正確に3が真の場合、aとbが真であるか、cとdが真です。次に、これらの各ケースを他の2つのうちの1つと論理積するだけです。

Wolframの真理値表

9
Cruncher

Karnaugh Mapsのようなロジックビジュアライゼーションツールを使用している場合、if(...)行で記述したい場合、完全なロジック用語を避けられない問題であることがわかります。 Lopinaはすでにそれを示しました、それをより簡単に書くことは不可能です。あなたは少しファクタリングすることができますが、あなたにとってもマシンにとっても読みにくいです。

カウントソリューションは悪くなく、あなたが本当に望んでいることを示しています。カウントを効率的に行う方法は、プログラミング言語によって異なります。 PythonまたはLinQの配列ソリューションは見た方がいいですが、注意してください、これは遅いです。ウルフの(a + b + x + y)== 3はうまく動作しますが、言語が「true」と1の場合、「true」が-1で表される場合は、-3をテストする必要があります

あなたの言語が真のブール値を使用している場合、明示的にそれをプログラムしようとすることができます(!= as XOR test)を使用します):

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がfalseで、他のすべてがtrueである他のタイプの場合、これは失敗する可能性があります。次に、ブール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);

このコードは、正確に3つの論理テスト(aの状態、bの状態、xとyの比較)を実行し、ここにある他のほとんどの回答よりも高速でなければなりません。ただし、コメントする必要があります。そうしないと、3か月後に理解できません。

8
Rolf

ここにはたくさんの良い答えがあります。これは、他の誰もまだ投稿していない代替の公式です。

 a ? (b ? (c ^ d) : (c && d)) : (b && c && d)
8
Alex D

最初の答えに似ていますが、純粋なJava:

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

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

コードを読みやすくするため、整数としてカウントすることを好みます。

7
La-comadreja

Pythonで、反復可能な要素の数がTrueであるかどうかを確認するには、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
7
Aaron Hall

4つのブール値のうち3つがtrueの場合にのみtrueを返します。

4つのブール値、a、b、x、yを指定すると、このタスクは次のCステートメントに変換されます。

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

紙上の(非プログラミング)ソリューションをお望みの場合は、KマップとQuine-McCluskeyアルゴリズムがお望みのものであり、ブール関数を最小化するのに役立ちます。

あなたの場合、結果は

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

これをプログラムで、固定されていない量の変数とカスタムの「しきい値」で行いたい場合、ブール値のリストを繰り返し処理し、「true」の出現をカウントするのは非常に簡単で簡単です。

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

あなたが望むものです。基本的に、私はあなたのコードを取り、実際には3がtrueであり3ではないかどうかのチェックを追加しました。

4
Shujal

再帰を含む答えのないプログラミングの質問? 考えられない!

「4つの真実のうち​​正確に3つ」の答えは十分にありますが、次のことができるという理由だけで、「nのうち正確にm個の真実」(そうでない場合、再帰は本当に価値がない)の一般化(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」にはあまり満足していませんが、今より良い名前を考えることはできません。..trueorが多すぎると再帰が停止することに注意してください。 =見つかったfalse値が多すぎます。

4

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";
3
Bill Ortell

読みやすさは大きな懸念事項であるため、記述的な関数呼び出しを使用できます(推奨される実装のいずれかをラップします)。この計算を複数の場所で実行する必要がある場合、関数呼び出しは再利用を実現するための最良の方法であり、実行していることを明確にします。

bool exactly_three_true_from(bool cond1, bool cond2, bool cond3, bool cond4)
{
    //...
}
3
(((a AND b) OR (x AND y)) AND ((a XOR b) OR (x XOR y)))

これは良い解決策であることを示すことができましたが、Sam Hocevarの答えは後で書いて理解するのも簡単です。私の本ではそれが良くなっています。

2
Jack Stout

あなたは私にインスピレーションを与えたので、ここに私が書いたいくつかの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をテストすることができます。

1
JPK