Проверьте, верно ли хотя бы два из трех логических значений - PullRequest
568 голосов
/ 19 июня 2010

Один из интервьюеров недавно задал мне этот вопрос: при наличии трех логических переменных a, b и c верните true, если хотя бы две из трех верны.

Мое решение следующее:

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

Он сказал, что это можно еще улучшить, но как?

Ответы [ 63 ]

6 голосов
/ 22 июня 2010

Я не думаю, что видел это решение:

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 значений, истинных», где первые два на самом деле верны, то оно должно идти быстрее, чем некоторые из более «нормальных» решений.

5 голосов
/ 21 июня 2010

AC решение.

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 голосов
/ 21 июня 2010
Function ReturnTrueIfTwoIsTrue(bool val1, val2, val3))
{
     return (System.Convert.ToInt16(val1) +
             System.Convert.ToInt16(val2) +
             System.Convert.ToInt16(val3)) > 1;
}

Слишком много способов сделать это ...

4 голосов
/ 22 июня 2010

Буквальная интерпретация будет работать на всех основных языках:

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

Но я бы, вероятно, упростил бы чтение для людей и расширил бы их до трех - это то, что многие программисты забывают:

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 голосов
/ 21 июня 2010
return 1 << $a << $b << $c >= 1 << 2;
4 голосов
/ 23 июня 2010

В качестве дополнения к превосходному сообщению @TofuBeer 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, что делает pdox самым быстрым в целом (на моем ноутбуке HP / Intel).

4 голосов
/ 20 июня 2010

Самый простой способ (ИМО), который не смущает и легко читается:

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

return ( a && ( b || c ) ) || ( b && c );
3 голосов
/ 25 июня 2010

Он, вероятно, не ищет ничего сложного, например, побитовые операторы сравнения (обычно не свернутые, но с булевыми значениями, крайне странно использовать побитовые операторы) или что-то очень округлое, например преобразование в int и суммирование их.* Самый прямой и естественный способ решить эту проблему - с помощью такого выражения:

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

Поместите его в функцию, если хотите, но это не очень сложно.Решение логически лаконично и эффективно.

3 голосов
/ 22 июня 2010

Этот вид читается лучше:

if (a) {
    return b || c;
} 
else {
    return b && c;
}
3 голосов
/ 29 января 2011

В С:

return !!a + !!b + !!c >= 2;
...