web-dev-qa-db-ja.com

3つのブール値のうち少なくとも2つが真であるかどうかを確認する

あるインタビュアーが最近私にこの質問をしました:3つのブール変数a、b、およびcが与えられた場合、3つのうち少なくとも2つが真であれば真を返します。

私の解決策は次のとおりです。

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

彼はこれがさらに改善されることができると言いました、しかし、どうですか?

567
user282886

書くよりもむしろ:

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は1回だけ、cは1回までテストされます。

参考文献

812

比較的単純な問題に答えるためにXORを使用する目的のためだけに...

return a ^ b ? c : a
484
Tim Stone

文字通りそれを実装しませんか? :)

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

Cでは、a+b+c >= 2(または非常に安全なものであれば!!a+!!b+!!c >= 2)を書くことができます。

TofuBeerのJavaバイトコードの比較に応えて、簡単なパフォーマンステストを示します。

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

これは私のマシンで次のものを印刷します(Intel Core 2 + Sun Java 1.6.0_15-b03とHotSpot Server VM(14.1-b02、混合モード)でUbuntuを実行している)。

1回目と2回目の繰り返し:

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がそのためにできることパフォーマンスを低下させるのではないでしょうか。

-client VMスイッチを付けて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インタプリタ でそれを実行するなら、それはほぼ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
212
Rotsor

この種の質問は、 カルノーマップ で解決できます。

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

そこから、最初の行には1つのグループ、最初の列には2つのグループが必要であると推測され、ポリ潤滑剤の最適な解が得られます。

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

読みやすさが目標です。コードを読む人はあなたの意図をすぐに理解しなければなりません。だからここに私の解決策があります。

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

return howManyBooleansAreTrue >= 2;
139
danatel
return (a==b) ? a : c;

説明:

a==bの場合、両方が真、または両方が偽です。両方とも真であれば、2つの真のブール値が見つかり、(aを返すことで)trueを返すことができます。両方ともfalseの場合、cがtrueであっても2つのtrueブール値はあり得ないため、(aを返すことによって)falseを返します。それが(a==b) ? aの部分です。 : cはどうですか? a==bがfalseの場合、aまたはbのどちらか一方が真でなければなりません。そのため、最初の真のブール値を見つけたので、cも真である場合に限り、cを返します。

133
pdox

あなたは演算子の短絡形を使う必要はありません。

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

これはあなたのバージョンと同じ数の論理演算を実行しますが、完全にブランチレスです。

34
moonshadow

これがテスト駆動の一般的なアプローチです。これまでに提供されてきたソリューションのほとんどほど「効率的」ではありませんが、明確で、テストされ、機能し、そして一般化されています。

public class CountBooleansTest extends TestCase {
    public void testThreeFalse() throws Exception {
        assertFalse(atLeastTwoOutOfThree(false, false, false));
    }

    public void testThreeTrue() throws Exception {
        assertTrue(atLeastTwoOutOfThree(true, true, true));
    }

    public void testOnes() throws Exception {
        assertFalse(atLeastTwoOutOfThree(true, false, false));
        assertFalse(atLeastTwoOutOfThree(false, true, false));
        assertFalse(atLeastTwoOutOfThree(false, false, true));
    }

    public void testTwos() throws Exception {
        assertTrue(atLeastTwoOutOfThree(false, true, true));
        assertTrue(atLeastTwoOutOfThree(true, false, true));
        assertTrue(atLeastTwoOutOfThree(true, true, false));
    }

    private static boolean atLeastTwoOutOfThree(boolean b, boolean c, boolean d) {
        return countBooleans(b, c, d) >= 2;
    }

    private static int countBooleans(boolean... bs) {
        int count = 0;
        for (boolean b : bs)
            if (b)
                count++;
        return count;
    }
}
27
Carl Manaster

それを合計しなさい。これは、ブール代数と呼ばれています。

  0 x 0 = 0
  1 x 0 = 0
  1 x 1 = 1

  0 + 0 = 0
  1 + 0 = 1
  1 + 1 = 0 (+ carry)

そこに真理値表を見れば、乗算はブール値であり、単純に加算はxorであることがわかります。

あなたの質問に答えるには:

return (a + b + c) >= 2
24
memet

それは本当にあなたが「改善した」という意味によって異なります。

もっと明確?

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

賢い?

boolean moreThanTwo(boolean a, boolean b, boolean c)
{
    return a == b ? a : c;
}

もっと一般的ですか?

boolean moreThanXTrue(int x, boolean[] bs)
{
    int count = 0;

    for(boolean b : bs)
    {
        count += b ? 1 : 0;

        if(count > x) return true;
    }

    return false;
}

もっとスケーラブル?

boolean moreThanXTrue(int x, boolean[] bs)
{
    int count = 0;

    for(int i < 0; i < bs.length; i++)
    {
        count += bs[i] ? 1 : 0;

        if(count > x) return true;

        int needed = x - count;
        int remaining = bs.length - i;

        if(needed >= remaining) return false;
    }

    return false;
}

もっと早く?

// Only profiling can answer this.

どれが「改善された」かは状況によって大きく異なります。

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

これはmap/reduceを使った別の実装です。これは、何十億ものブール値に対応します。© 分散環境では。 MongoDBを使う:

ブール値のデータベースvaluesを作成する:

db.values.insert({value: true});
db.values.insert({value: false});
db.values.insert({value: true});

マップを作成して関数を減らします。

編集:好きです CurtainDog's答え map/reduceをジェネリックリストに適用することについてです。そこで、値を数えるべきかどうかを決定するコールバックを取るmap関数を使います。

var mapper = function(shouldInclude) {
    return function() {
        emit(null, shouldInclude(this) ? 1 : 0);
    };
}

var reducer = function(key, values) {
    var sum = 0;
    for(var i = 0; i < values.length; i++) {
        sum += values[i];
    }
    return sum;
}

ランニングマップ/リデュース:

var result = db.values.mapReduce(mapper(isTrue), reducer).result;

containsMinimum(2, result); // true
containsMinimum(1, result); // false


function isTrue(object) {
    return object.value == true;
}

function containsMinimum(count, resultDoc) {
    var record = db[resultDoc].find().next();
    return record.value >= count;
}
14
Anurag

直接コードの別の例:

int  n = 0;
if (a) n++;
if (b) n++;
if (c) n++;
return (n >= 2);

明らかに最も簡潔なコードではありません。

補遺

これのもう一つの(やや最適化された)バージョン:

int  n = -2;
if (a) n++;
if (b) n++;
if (c) n++;
return (n >= 0);

0に対する比較は2に対する比較よりも速い(またはおそらく少ない)コードを使用すると仮定して、これは少し速く実行されるかもしれません。

13
David R Tribble

ここで(今のところ)答えをとる:

public class X
{
    static boolean a(final boolean a, final boolean b, final boolean c)
    {
    return ((a && b) || (b && c) || (a && c));
    }

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

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

    static boolean d(final boolean a, final boolean b, final boolean c)
    {
    return ((a?1:0)+(b?1:0)+(c?1:0) >= 2);
    }
}

そして逆コンパイラー(javap -c X> results.txt)を通してそれらを実行します。

Compiled from "X.Java"
public class X extends Java.lang.Object{
public X();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method Java/lang/Object."<init>":()V
   4:   return

static boolean a(boolean, boolean, boolean);
  Code:
   0:   iload_0
   1:   ifeq    8
   4:   iload_1
   5:   ifne    24
   8:   iload_1
   9:   ifeq    16
   12:  iload_2
   13:  ifne    24
   16:  iload_0
   17:  ifeq    28
   20:  iload_2
   21:  ifeq    28
   24:  iconst_1
   25:  goto    29
   28:  iconst_0
   29:  ireturn

static boolean b(boolean, boolean, boolean);
  Code:
   0:   iload_0
   1:   ifeq    20
   4:   iload_1
   5:   ifne    12
   8:   iload_2
   9:   ifeq    16
   12:  iconst_1
   13:  goto    33
   16:  iconst_0
   17:  goto    33
   20:  iload_1
   21:  ifeq    32
   24:  iload_2
   25:  ifeq    32
   28:  iconst_1
   29:  goto    33
   32:  iconst_0
   33:  ireturn

static boolean c(boolean, boolean, boolean);
  Code:
   0:   iload_0
   1:   iload_1
   2:   iand
   3:   iload_1
   4:   iload_2
   5:   iand
   6:   ior
   7:   iload_2
   8:   iload_0
   9:   iand
   10:  ior
   11:  ireturn

static boolean d(boolean, boolean, boolean);
  Code:
   0:   iload_0
   1:   ifeq    8
   4:   iconst_1
   5:   goto    9
   8:   iconst_0
   9:   iload_1
   10:  ifeq    17
   13:  iconst_1
   14:  goto    18
   17:  iconst_0
   18:  iadd
   19:  iload_2
   20:  ifeq    27
   23:  iconst_1
   24:  goto    28
   27:  iconst_0
   28:  iadd
   29:  iconst_2
   30:  if_icmplt   37
   33:  iconst_1
   34:  goto    38
   37:  iconst_0
   38:  ireturn
}

?:のものはあなたのオリジナルの修正版より少し優れていることがわかります。最高のものは、完全に分岐を回避するものです。分岐予測を誤って推測するとCPUがストールする可能性があるため、これは、ほとんどの場合、少ない命令の観点からは適切であり、CPUの分岐予測部分には適しています。

私は最も効率的なものが全体的にムーンシャドウからのものであると思います。平均して最も少ない命令を使用し、CPU内でパイプラインがストールする可能性を減らします。

100%確実にするには、各命令のコスト(CPUサイクル)を調べる必要があります。残念ながら、すぐには入手できません(ホットスポットのソースを調べてから、当時のCPUベンダーの仕様を確認する必要があります)。生成された各命令に対して使用されます。

コードの実行時分析については、Rotsorによる最新の回答を参照してください。

13
TofuBeer

最も明白な改良点は次のとおりです。

// There is no point in an else if you already returned.
boolean atLeastTwo(boolean a, boolean b, boolean c) {
    if ((a && b) || (b && c) || (a && c)) {
        return true;
    }
    return false;
}

その後

// There is no point in an if(true) return true otherwise return false.
boolean atLeastTwo(boolean a, boolean b, boolean c) {
    return ((a && b) || (b && c) || (a && c));
}

しかし、それらの改善は軽微です。

12
TofuBeer

これを行うには別の方法がありますが、それほど良い方法ではありません。

return (Boolean.valueOf(a).hashCode() + Boolean.valueOf(b).hashCode() + Boolean.valueOf(c).hashCode()) < 3705);

Booleanハッシュコード値は、trueの場合は1231、falseの場合は1237に固定されているため、<= 3699を使用することもできます。

12
barrowc

私は三項(一番上の答えからreturn a ? (b || c) : (b && c);)が好きではありません、そして私は誰かがそれを言及するのを見たとは思いません。これは次のように書かれています。

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

Clojure に:

(defn at-least [n & bools]
  (>= (count (filter true? bools)) n)

使用法:

(at-least 2 true false true)
8
Vagif Verdi

私はまだ私がこの解決策を見たとは思わない:

boolean atLeast(int howMany, boolean[] boolValues) {
  // check params for valid values

  int counter = 0;
  for (boolean b : boolValues) {
    if (b) {
      counter++;

      if (counter == howMany) {
        return true;
      }
    }
  }
  return false;
}

その利点は、それがあなたが探している数に達すると、それが壊れることです。そのため、最初の2つが実際に当てはまる場合、これが「この1,000,000個の値のうち少なくとも2個が当てはまる」という場合、それはより一般的ないくつかの解決策よりも速くなります。

6
Joe Enos

コードをどのように改善すべきかは明記されていないので、コードをより面白くすることによってコードを改善するように努力します。これが私の解決策です:

boolean atLeastTwo(boolean t, boolean f, boolean True) {
    boolean False = True;
    if ((t || f) && (True || False)) 
        return "answer" != "42";
    if (t && f) 
        return !"France".contains("Paris");
    if (False == True) 
        return true == false;
    return Math.random() > 0.5;
}

このコードが機能するかどうかと誰かが疑問に思う場合は、これと同じロジックを使用して単純化します。

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    if ((a || b) && (c)) 
        return true;
    if (a && b) 
        return true;
    if (true) 
        return false;
    // The last line is a red herring, as it will never be reached:
    return Math.random() > 0.5; 

}

これはさらに以下のようにまとめることができます。

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

しかし今ではもう面白くないです。

6
Bruce Attah

ブールを整数に変換して、この簡単なチェックを実行できます。

(int(a) + int(b) + int(c)) >= 2
6
vine'th

Cソリューション.

int two(int a, int b, int c) {
  return !a + !b + !c < 2;
}

またはあなたが好むかもしれません:

int two(int a, int b, int c) {
  return !!a + !!b + !!c >= 2;
}
5
Suvega
Function ReturnTrueIfTwoIsTrue(bool val1, val2, val3))
{
     return (System.Convert.ToInt16(val1) +
             System.Convert.ToInt16(val2) +
             System.Convert.ToInt16(val3)) > 1;
}

やり方が多すぎます...

5
Duby

@TofuBeerの優れた投稿に加えて、@ pdox pdoxの回答を検討してください。

static boolean five(final boolean a, final boolean b, final boolean c)
{
    return a == b ? a : c;
}

"javap -c"で与えられるように、その逆アセンブル版も考えてください。

static boolean five(boolean, boolean, boolean);
  Code:
    0:    iload_0
    1:    iload_1
    2:    if_icmpne    9
    5:    iload_0
    6:    goto    10
    9:    iload_2
   10:    ireturn

pdoxの回答は、前のどの回答よりも少ないバイトコードにコンパイルされます。実行時間は他の人とどのように違いますか?

one                5242 ms
two                6318 ms
three (moonshadow) 3806 ms
four               7192 ms
five  (pdox)       3650 ms

少なくとも私のコンピューターでは、pdoxの答えは@moonshadow moonshadowの答えよりほんの少し速いので、(私のHP/Intelラップトップでは)pdoxは全体的に最速です。

4
Barzee

文字通りの解釈は、すべての主要言語で機能します。

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

しかし、私はおそらく、人々が読みやすく、3人以上に拡張できるようにしたいと思います。これは、多くのプログラマーによって忘れられているようです。

boolean testBooleans(Array bools)
{
     int minTrue = ceil(bools.length * .5);
     int trueCount = 0;

     for(int i = 0; i < bools.length; i++)
     {
          if(bools[i])
          {
               trueCount++;
          }
     }
     return trueCount >= minTrue;
}
4
blakecallens
return 1 << $a << $b << $c >= 1 << 2;
4
Kevin

混乱せず、また読みやすくもない最も簡単な方法(IMO):

// Three booleans, check if two or more are true

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

そのはず:

(a || b && c) && (b || c && a)

また、trueが自動的に1に、false0に変換すると、

(a + b*c) * (b + c*a) > 0
3

Rubyでは:

[a, b, c].count { |x| x } >= 2

これはJRVMyのJavaVM上で実行できます。 ;-)

3
user373826

私が質問を見たときに私が最初に思ったのは、

int count=0;
if (a)
    ++count;
if (b)
    ++count;
if (c)
    ++count;
return count>=2;

他の投稿を見た後で、私はそれを認めた

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

はるかにエレガントです。相対的なランタイムはどうだろうか。

いずれにせよ、しかし、私はこの種の解決策はの解決策よりもはるかに優れていると思います

return a&b | b&c | a&c;

多様性があるため、より簡単に拡張できます。後でテストする必要がある4番目の変数を追加した場合はどうなりますか?実行時に変数の数が決定され、未知のサイズのブール値の配列が渡された場合はどうなりますか?数え上げに依存する解決策は、可能性のあるすべての組み合わせのリストに依存する解決策よりもはるかに簡単に拡張できます。また、すべての可能な組み合わせをリストするとき、私は間違いを犯すのがはるかに簡単であると思います。 「any 3 of 4」のコードを書いてみたり、見逃したり複製したりしないようにしてください。それでは "any 5 of 7"で試してみてください。

3
Jay

彼はおそらく、ビット単位の比較演算子のような複雑なもの(通常は複雑ではありませんが、ビット演算子を使用するのは非常に奇妙です)や、intに変換して合計するような非常に迂回するものを探していません。

これを解決する最も直接的で自然な方法は、次のような表現です。

a ? (b || c): (b && c)

お望みであれば関数に入れてください。しかしそれほど複雑ではありません。解決策は論理的に簡潔で効率的です。

3
stinky472

この種のものはよく読んでいます:

if (a) {
    return b || c;
} 
else {
    return b && c;
}
3

Cでは:

return !!a + !!b + !!c >= 2;
3
Matt Joiner

真理値表で計算します。

return (a & b) | (c & (a ^ b));
3
z-index

実際のコーディング能力よりも、問題の解決方法や考え方についての質問です。

もう少し簡潔なバージョンは

return((a ^ b)&&(b ^ c))^ b

しかし、前のポスターが言ったように、私が作業していたコードでこれを見た場合、誰かが耳にします。 :)

2
Kintar

X = OR(a + b、c)

a b c X

1 1 0 1

0 0 1 1

0 1 1 1

2
dai
int count=0;

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    if (a)
        count++;
    if (b)
        count++;
    if (c)
        count++;

    if (count>1)
        return true;
    else
        return false;
}
2
endy

Java 8の通貨、私は本当にこのようなものを好む:

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    return Stream.of(a, b, c).filter(active -> active).count() >= 2;
}
2
coder

私はこの解決策を見つけました。

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    bool result = !(a ^ b ^ c) && !(!a & !b & !c) || (a & b & c);
    return result;
}

この質問に対する最善の答えは、「従業員として、パフォーマンスに必要な場合に効率を維持しながら、自分の意味を明確にするために私がそれを書くことが重要です」ということです。これを書く方法は次のとおりです。

function atLeastTwoAreTrue(a, b, c) {
    return (a && b) || (b && c) || (a && c);
}

実際には、テストは非常に工夫されているので、あなたが単純なコメントでそれを受け入れるならば、最速で最も不可解な方法を書くことは完全に受け入れられます。しかし、一般に、このワンライナーの世界では、この世界でもっと読みやすいコードが必要です。 :-)

2
ZaBlanc

3つのブール値をA、B、Cとします。

K-MAPを使って、ブール式を使うことができます。

この場合、ブール式はA(B + C)+ Cになります。

またはif((A &&(B || C))|| C){trueを返す。それ以外の場合はfalseを返します。

2
Egalitarian

提起された問題の2と3は明らかに魔法のような数字です。 「正しい」答えは、インタビュアーがあなたのブール論理を理解しようとしていたか(そしてこの点でpdoxの答えが破綻する可能性があるとは思わない)、あるいはあなたが建築問題について理解しているかどうかによって異なります。

私は、任意の条件を持つあらゆる種類のリストを受け付けるmap-reduceソリューションを採用したいと思います。

2
CurtainDog

ちなみに、これは全加算器の単なるキャリーアウトビットです。ハードウェアでは、論理演算を使用して、さまざまなブール式に基づいて最適な回路を決定できます。私は、伝統的なXOR解決策は、ポスターが提示した簡潔ではない表現よりも多くの努力を要すると思います。

2
Ben Manes

私が他の人が指摘したことを見たことがないということの一つは、就職の面接の「私にいくつかのコードを書いてください」のセクションでやるべき標準的なことはまたは「それに完全に満足していますか」または「できるだけ最適化されていますか?」あなたが言うとあなたは終わった。 「これはどのように改善されるのでしょうか」と「あなたはそれをどのように改善するのか」と聞いた可能性があります。この場合、if(x) return true; else return false;イディオムを単なるreturn xに変更することは改善です - しかし、彼らがあなたが質問にどう反応するかを見たいだけの時があることに注意してください。インタビュアーの中には、完璧なコードに欠陥があると主張する人もいるだろうと聞いています。

2
Kate Gregory

(a||b) && (a||c) - Javaでは、OPの6つではなく3つの比較を使用します。

間違って、私は以前にチェックしたはずです。

2
d1val

目的が3つのオペランドに対してビットごとの2/3の値を返すことである場合、算術および反復アプローチは比較的効果的ではない傾向があります。多くのCPUアーキテクチャでは、良い形式は「return((a | b)&c)|(a&b);」です。それは4つのブール演算を取ります。シングルアキュムレータマシン(小型の組み込みシステムで一般的)では、1バイトあたり合計7命令を使用する傾向があります。 "return(a&b)|(a&c)|(b&c);"という形式見栄えはいいかもしれませんが、1つのアキュムレータマシンでは、5つのブール演算、または1バイトあたり9つの命令が必要です。

ちなみに、CMOSロジックでは、「3つのうち2つではない」を計算するには12個のトランジスタが必要です(比較のため、インバータには2個、2入力NANDまたはNORには4個、そして3入力NANDまたはNORには6が必要です。

2
supercat

三項演算子はオタクジュースを流しますが、混乱を招く可能性があります(コードの保守性が低下するため、バグインジェクションの可能性が高まります)。 Jeff Attwood はここでそれをよく言った:

これは、まったく意味のない1回の書き込み時の節約と、数十回の読み取り時の解釈のペナルティとのトレードオフの完璧な例です。

三項演算子を避けて、私は以下の関数を作成しました:

function atLeastTwoTrue($a, $b, $c) {
        $count = 0;

        if ($a) { $count++; }
        if ($b) { $count++; }
        if ($c) { $count++; }

        if ($count >= 2) {
                return true;
        } else {
                return false;
        }
}

他の解決策と同じくらいクールですか。わかりやすいですか。はい。それは保守性が良く、バグの少ないコードになるでしょうか。はい。

2
labratmatt

パフォーマンスのコンテキストではなく、優れたコード(再利用可能な拡張可能で読み取り可能なコード)

     static boolean trueBooleans (int howMany,boolean ... bools)
     {
      int total = 0;

      for (boolean b:bools)
        if (b && (++total == howMany)) return true;


      return false;
    }

Javaを書くときの私の控え目な意見では、予期しない変更を簡単に処理してコードを複製しないことが、簡潔な(スクリプト言語のドメイン)または高速なプログラムよりも重要です。

2
teodozjan

C# では、頭の上からは、

public bool lol(int minTrue, params bool[] bools)
{
    return bools.Count( ( b ) => b ) >= minTrue;
}

かなり速いはずです。

呼び出しは次のようになります。

lol( 2, true, true, false );

この方法では、ルールをメソッドに埋め込むのではなく、呼び出し側にルールを任せます(2つは当てはまります)。

2
Aaron

この問題に対する非限定的な解決策は次のとおりです。

a'bc + abc' + abc + ab'c

K-Mapsを使うと、次のようになります。

bc + ab + ac

A'bcおよびabc '最小項に排他的論理和を使用し、abcおよびab'c最小項を組み合わせることで、これをさらに減らすことができます。

b(a ^ c) + ac
2
SirensOfTitan

これはどう:

(a - b) ? c : a
1
binary_baba

Java 8の Stream 機能を使用して、これに別のアプローチを取ります。任意の数の任意のブール値に対して。すべての要素を処理する前にStreamが制限に達すると、Streamは短絡します。

public static boolean atLeastTrue(int amount, Boolean ... booleans) {
    return Stream.of(booleans).filter(b -> b).limit(amount).count() == amount;
}

public static void main(String[] args){
    System.out.println("1,2: " + atLeastTrue(1, true, false, true));
    System.out.println("1,1: " + atLeastTrue(1, false, true));
    System.out.println("1,0: " + atLeastTrue(1, false));
    System.out.println("1,1: " + atLeastTrue(1, true, false));
    System.out.println("2,3: " + atLeastTrue(2, true, false, true, true));
    System.out.println("3,2: " + atLeastTrue(3, true, false, true, false));
    System.out.println("3,3: " + atLeastTrue(3, true, true, true, false));
}

出力:

1,2: true
1,1: true
1,0: false
1,1: true
2,3: true
3,2: false
3,3: true
1
mkobit

子:

if (!!a + !!b + !!c >= 2)
1
Matt Joiner
public static boolean atLeast(int atLeastToBeTrue, boolean...bools){
    int booleansTrue = 0;
    for(boolean tmp : bools){
        booleansTrue += tmp ? 1 : 0;
    }
    return booleansTrue >= atLeastToBeTrue;
}

varargs a.k.a at least :-)から、何個のboolean[]を真にしたいかを選ぶことができます。

0
To Kra
関数atLeastTwoTrue($ a、$ b、$ c){
 
 int count = 0; 
 count =(a?count + 1:count); 
 count =(b?count + 1:count); 
 count =(c?count + 1:count); 
 return(count> = 2); 
 ]] 
0
itpatil

もしブール値を数に変換し、その数が2のべき乗でなければ、少なくとも2つの真理があります。

a*4 + b*2 + c*1 = N
return( N != 0 && (N&(N-1)) != 0)

私はただ選択肢を与えています。

0

私には、3つのうち3つはまったく任意の数であり、関数は任意の数で機能するはずです。それで、質問に答えるために、私は配列のxが真ならばうまくいくであろう関数を書きたいでしょう、例えば、

bool istrue ( int x, bool[] list)
    y = count true in list
    return y >= x
0
Derek Organ

関数koは答えを返します。

static int ho(bool a)
{
    return a ? 1 : 0;
}

static bool ko(bool a, bool b, bool c)
{
    return ho(a) + ho(b) + ho(c) >= 2 ? true : false;
}
0
Dhananjay

問題を解決するために三項演算子を使用する最も簡単な形式は、次のとおりです。

return a ? (b ? true : c) : (b ? c : false);

また、要件の二重否定を使用して解決策を見つけることに投資することもできます。つまり、少なくとも2つの真の値の代わりに、最大1つの偽の値を満たす必要があります。

0
Melvin Protacio

もう一つ:

return a? b||c : b&&c
0
nabil london