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


163

True4つのブール値のうち3つがtrueの場合にのみ戻りたい。

私が得た最も近いものは(x ^ y) ^ (a ^ b)

私は何をすべきか?


10
うーん、数式なしで考えることができる唯一の方法は、カウントを使用することです。良い質問!:)
私はキャビック14年

10
あなたの考えは悪くありませんが、否定を取らなければなりません:否定not a ^ not b ^ not c ^ not dされた値の1つが真であるときに真です。これは、元の値から、正確に1つが偽であったことを意味します。
インゴ

23
この詳細の背後にある実際の問題は何ですか?
Wolf

5
@Ingo not a ^ not b ^ not c ^ not d not one true is where AND AND where where false。
NameSpace 2014年

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)は、に変換するboolint期待値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に質問します。」彼が論理回路またはそのようなものを設計しているのでない限り(それから彼は間違ったサイトにいるでしょう)、これを行うための最良の方法は、読みやすい方法です。
NothingsImpossible 2014年

2
@NothingsImpossible質問についてXYはありません。これは、プログラミングにおけるかなり一般的な問題の解決についての明確でわかりやすい質問です。Yは無関係です。
ЯрославРахматуллин

ありがとう!これは本当に私がやろうとていることですが、私の考えはあまりにも不器用だったので、ブール論理に到達しました。
Simon Kuang

3
if (!!a + !!b + !!c + !!d == 3)コンパイラーがこれを最適化するかどうかはわかりませんが、書くのは簡単です
phuclv '10

2
c ++では、boolからintへのキャストは必要ないことに注意してください。
PlasmaHH 2014年

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は純粋なブール論理での最良の答えです。
ブリリアント

2
#2の
Wolframalpha

68

これが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):

17
+1これは、Pythonに正しく変換することで問題を解決します。
Wolf 14

人々はPythonのブールコンテキストでゼロ以外の整数を返す可能性があるため、これは少し危険です。古いCトリックはPythonでも機能しますa=5;not not a == 1。実際のブール型を持たないことの欠点。
Voo

@Voo我々はまた、持っているbool:)
thefourtheye

@thefourtheyeああそうです、二重否定のトリック/ハックよりもずっといいです。
Voo

1
または...または....または....それを行うには1つ、できれば1つだけの明白な方法が必要です。:-/ :-)
rz。

53

長いが非常に単純な(選言的)正規形:

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

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


2
@Benは、さまざまな通常の形式を提供します。これはすでに(DNF)にあります。
2014年

8
いかが(a & b & (c ^ d)) | ((a ^ b) & c & d)ですか?
user253751 14年

2
はい、@ immibis、Wolfram Alphaによると、そのDNFは私が書いた式なので、同じブール関数です。
ガストンBengolea

2
なぜなら、コードを読んでいる人は、他の回答よりも何が試みられているのかをより早く理解できると思うからです。
Boluc Papuccuoglu 2014年


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

または、必要に応じて、これらすべてを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;
}

12
それに負けないで。毎回読みやすさが賢さを上回ります。+1
MikeTheLiar 14年

20

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


18

SOは、単なる論理的な問題ではなくプログラミングの質問の場合、その答えは明らかにプログラミング言語の選択に依存することを覚えておいてください。一部の言語は、他の言語には珍しい機能をサポートしています。

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

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

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


2
これが私が投稿しようとしていた答えです。ただし、使用するプログラミング言語にもよりますが、必要な答えは-3です。VBでは、True = -1です。
トムコリンズ


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

最初の式trueは、4から1または3を検索します。2番目の式は、4から0または1(場合によっては2)を削除しますtrue


11

Java 8、false値をフィルターで除外し、残りのtrue値をカウントします。

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は、Art of Computer Programmingの第4巻のセクション7.1.2でこのタイプの関数について言及しています。

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

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

クヌースのこれはあなたが通常の演算子を使用して7回の未満の操作でこれを行うことができないことを意味し、最適であることを示しています&&, || , ^, <,>

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

x + y + a + b == 3

これはあなたの意図をかなり明確にします。


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

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

ピジョンホールの原理では、厳密に3が真である場合、aとbが真であるか、cとdが真です。次に、これらの各ケースを他の1つと正確に結合するだけです。

Wolfram真理値表


これは、NameSpaceの2番目のソリューションに相当します。
ブリリアント

@Brilliand私とは違うようです。彼のxorsはすべて一緒になって3または1をすべて取得し、2つの異なるグループから少なくとも1つを要求することで、1を持つものを除外します。(1または3として要約され、少なくとも2)。鉱山は、別個のグループの1つからの両方と、もう一方のグループからの正確な1つを必要とします。
ランチャー2014年

その意味で同等のものを意味するのであればmine <=> his、私はこれが予想されるので何を言うべきかわかりません。
ランチャー2014年

この答えは、NameSpaceの(以前の)答えがカバーしなかった新しいものを何も追加せずに、NameSpaceの2番目のソリューションが良いのとまったく同じように良いことを意味したと思います。とにかく、私は賛成票を投じます。
ブリリアント

8

Karnaugh Mapsなどのロジック視覚化ツールを使用している場合、これは、if(...)行で記述したい場合、完全な論理用語を回避できない問題であることがわかります。ロピナはそれをすでに示しました、それをより簡単に書くことは不可能です。あなたは少し因数分解できますが、あなたにとってもマシンにとっても読みにくいままです。

カウントソリューションは悪くなく、彼らはあなたが本当に何を求めているかを示します。効率的にカウントする方法は、プログラミング言語によって異なります。Python oder LinQを使用したアレイソリューションはよく見ることができますが、これは遅いことに注意してください。ウルフの(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が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

ここには多くの良い答えがあります。ここに誰もまだ投稿していない代替の処方があります:

 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

ではPythonの、要素の反復可能なの何を見ている真、使用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マップと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
バーのオーバーヘッドとはどういう意味ですか?リストが下に移動していることに気づきました。
NameSpace 2014年

3
@NameSpaceこれは、人々が「しない」を表現するために使用するIMOの多くの表記法の1つです。

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 :)
ウルフ

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

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


4

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

「4つの真のうち3つだけ」という答えは十分ありますが、次のことができるという理由だけで、「真のうち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つが予想どおりtrueだったため)。"true"と "falses"という単語には満足できませんが、現在のところ、より適切な名前を付けることはできません。... 見つかった値が多すぎtrue たり多すぎたりすると、再帰が停止しますfalse


@FélixSaparelli:「真実」がここに当てはまるかどうかわからない... 1つだけで満足しているように聞こえるでしょうtrue。たぶんのようなものcontainsNumberOfTrueValues()。余談ですが、Smalltalkの命名は、これにははるかに適していますdoesArray: someBooleans startingAt: anIndex containNumberOfTrueValues: anExpectedNumber foundSofar: aNumberFoundSoFar。おそらく一部のJava開発者の好みには長すぎるかもしれませんが、Smalltalkerは適切な名前を恐れることはありません;-)
Amos M. Carpenter

それは主に滑稽でした。そしてcontainsTruth、私はそれはかなり大丈夫だと考えているような手段は、文字通り、「真実の一部非公開の量が含まれています」。
フェリックス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.