Интервьюер недавно задал мне этот вопрос: учитывая три логические переменные, a, b и c, вернуть true, если хотя бы две из трех верны.
Мое решение следующее:
boolean atLeastTwo(boolean a, boolean b, boolean c) {
if ((a && b) || (b && c) || (a && c)) {
return true;
}
else{
return false;
}
}
Он сказал, что это может быть улучшено дальше, но как?
java
boolean
boolean-logic
user282886
источник
источник
atLeastTwo(iWantYou, iNeedYou, imEverGonnaLoveYou)
Ответы:
Вместо того чтобы писать:
Написать:
Что касается самого выражения, примерно так:
или это (что вам легче понять):
Он тестирует
a
иb
ровно один раз, иc
самое большее один раз.Ссылки
источник
return hasGoodAttendance ? (passedCoursework || passed Exam) : (passedCoursework && passedExam)
, это выглядит хорошо для меня.atLeastTwo(hasgoodAttendance, passedCoursework, passedExam)
. Идея «по крайней мере 2 bools являются правдой» является достаточно общей, чтобы заслужить свою собственную функцию.Просто ради использования XOR для решения относительно простой задачи ...
источник
Почему бы не реализовать это буквально? :)
В C вы можете просто написать
a+b+c >= 2
(или!!a+!!b+!!c >= 2
быть в безопасности).В ответ на сравнение байт-кода Java TofuBeer , вот простой тест производительности:
На моем компьютере будет напечатано следующее (работает Ubuntu на Intel Core 2 + Sun java 1.6.0_15-b03 с виртуальной машиной сервера HotSpot (14.1-b02, смешанный режим)):
Первая и вторая итерации:
Более поздние итерации:
Интересно, что может сделать Java VM, которая со временем снижает производительность для (a + b + c> = 2) случая.
И вот что происходит, если я запускаю Java с
-client
коммутатором VM:Тайна ...
И если я запускаю его в GNU Java Interpreter , он работает почти в 100 раз медленнее, но тогда
a&&b || b&&c || a&&c
выигрывает версия.Результаты от Tofubeer с последним кодом под управлением OS X:
Результаты Пола Уогланда с Mac Java 1.6.0_26-b03-383-11A511
источник
a+b+c >= 2
: это не работает с негативами, верно? Возможно, вам придется сделать!!a
это, я не уверен.Этот тип вопросов можно решить с помощью карты Карно :
из которого вы заключаете, что вам нужна группа для первого ряда и две группы для первого столбца, получая оптимальное решение для полигенных смазок:
источник
Читабельность должна быть целью. Кто-то, кто читает код, должен немедленно понять ваше намерение. Так вот мое решение.
источник
Seq(true, true, false).map(if (_) 1 else 0).sum >= 2
Объяснение:
Если
a==b
, тогда оба являются истинными или оба являются ложными. Если оба имеют значение true, мы нашли два наших истинных логических значения и можем вернуть true (путем возвратаa
). Если оба являются ложными, не может быть двух истинных логических значений, даже еслиc
это правда, поэтому мы возвращаем ложное (возвращаяa
). Это(a==b) ? a
часть. Как насчет: c
? Что ж, еслиa==b
false, то в точности одно изa
илиb
должно быть true, поэтому мы нашли первое истинное логическое значение, и единственное, что остается важным, это еслиc
также true, поэтому мы возвращаемсяc
в качестве ответа.источник
a
иb
согласны, они имеют большинство голосов, так что идите с тем, что есть, иначе они не согласны, так жеc
как и решающий голос»Вам не нужно использовать формы короткого замыкания операторов.
return (a & b) | (b & c) | (c & a);
Он выполняет то же количество логических операций, что и ваша версия, но совершенно без ветвей.
источник
Вот общий подход, основанный на тестировании. Не настолько «эффективный», как большинство предлагаемых решений, но понятный, проверенный, работающий и обобщенный.
источник
Суммировать. Это называется булевой алгеброй по причине:
Если вы посмотрите на таблицы истинности там, то увидите, что умножение логическое и, а просто сложение - это xor.
Чтобы ответить на ваш вопрос:
источник
return ((a?1:0) + (b?1:0) + (c?1:0)) >= 2
.источник
Это действительно зависит от того, что вы подразумеваете под «улучшенным»:
Яснее?
Terser?
Более общий?
Более масштабируемый?
Быстрее?
Какой из них «улучшен», сильно зависит от ситуации.
источник
Вот еще одна реализация, использующая карту / уменьшить. Это хорошо масштабируется до миллиардов логических величин © в распределенной среде. Использование MongoDB:
Создание базы данных
values
логических значений:Создавая карту, уменьшите функции:
Редактировать : мне нравится ответ CurtainDog о применении map / lower для общих списков, так что здесь идет функция карты, которая принимает обратный вызов, который определяет, следует ли считать значение или нет.
Запуск карты / уменьшить:
источник
Принимая ответы (пока) здесь:
и запустить их через декомпилятор (javap -c X> results.txt):
Вы можете видеть, что?: Немного лучше, чем исправленная версия вашего оригинала. Лучшим является тот, который вообще избегает ветвления. Это хорошо с точки зрения меньшего количества инструкций (в большинстве случаев) и лучше для частей ЦП с предсказанием переходов, поскольку неправильное предположение в прогнозе ветвления может привести к остановке ЦП.
Я бы сказал, что самый эффективный - тот, что из лунной тени в целом. Он использует наименьшее количество инструкций в среднем и снижает вероятность остановки конвейера в ЦП.
Чтобы быть на 100% уверенным, вам понадобится выяснить стоимость (в циклах ЦП) для каждой инструкции, которая, к сожалению, недоступна (вам нужно будет посмотреть источник горячей точки, а затем спецификации поставщиков ЦП на время берется за каждую сгенерированную инструкцию).
Смотрите обновленный ответ Rotsor для анализа кода во время выполнения.
источник
Еще один пример прямого кода:
Это не самый лаконичный код, очевидно.
добавление
Еще одна (немного оптимизированная) версия этого:
Это может выполняться немного быстрее, если предположить, что сравнение с 0 будет использовать более быстрый (или, возможно, менее) код, чем сравнение с 2.
источник
++n
быстрее, чемn++
потому, что вам нужно создать еще одну копию, прежде чем делать приращение .n
выше) любой приличный компилятор скомпилирует каждую++
операцию в одну инструкцию CPU, будь то до или после.Еще один способ сделать это, но не очень хороший:
Значения
Boolean
хеш-кода фиксированы на 1231 для истины и 1237 для ложных, поэтому могли бы в равной степени использовать<= 3699
источник
Наиболее очевидный набор улучшений:
а потом
Но эти улучшения незначительны.
источник
Мне не нравится троичный (
return a ? (b || c) : (b && c);
из верхнего ответа), и я не думаю, что видел, чтобы кто-то упоминал об этом. Это написано так:источник
В Clojure :
Применение:
источник
Я не думаю, что видел это решение еще:
Его преимущество в том, что как только он достигает нужного вам числа, он ломается. Таким образом, если это «как минимум 2 из этих 1 000 000 значений истинны», где первые два на самом деле верны, то это должно идти быстрее, чем некоторые из более «нормальных» решений.
источник
boolean ... boolValues
так, что проще позвонить, но все равно принимает массивМы можем преобразовать bools в целые числа и выполнить эту простую проверку:
источник
Поскольку не было указано, как код должен быть улучшен, я постараюсь улучшить код, сделав его более забавным. Вот мое решение:
Если кому-то интересно, работает ли этот код, приведем упрощение с использованием той же логики:
}
Это может быть сведено к следующему:
Но теперь это уже не смешно.
источник
Слишком много способов сделать это ...
источник
Решение переменного тока.
или вы можете предпочесть:
источник
источник
Самый простой способ (IMO), который не смущает и легко читается:
источник
(C && (A || B)) || (A && B)
только что изменил имена * переменных`Буквальный перевод будет работать на всех основных языках:
Но я бы, вероятно, упростил бы чтение для людей и увеличил бы их до трех, что многие программисты забывают:
источник
В дополнение к отличному сообщению @TofuBeer TofuBeer рассмотрим ответ @pdox pdox:
Рассмотрим также его дизассемблированную версию, заданную "javap -c":
Ответ pdox компилируется в меньший байт-код, чем любой из предыдущих ответов. Как его время выполнения сравнивается с другими?
По крайней мере, на моем компьютере ответ pdox немного быстрее, чем ответ @moonshadow moonshadow, что делает pdox самым быстрым в целом (на моем ноутбуке HP / Intel).
источник
В рубине:
[a, b, c].count { |x| x } >= 2
Который может быть запущен в JRuby на JavaVM. ;-)
источник
Он, вероятно, не ищет ничего сложного, например, побитовые операторы сравнения (обычно не свернутые, но с булевыми значениями, крайне странно использовать побитовые операторы) или что-то очень обходное, например, преобразование в int и суммирование их.
Самый прямой и естественный способ решить эту проблему - с помощью такого выражения:
Поместите это в функцию, если хотите, но это не очень сложно. Решение логически лаконично и эффективно.
источник
В С:
источник