Древние греки называли эти вещи одинарными и вдвойне четными числами. Примером единственного четного числа является 14. Оно может быть разделено на 2 один раз, и в этот момент оно становится нечетным числом (7), после чего оно больше не делится на 2. Двойное четное число равно 20. Оно может быть разделено на 2 дважды, а затем становится 5.
Ваша задача - написать функцию или программу, которая принимает целое число в качестве входных данных и выводит количество раз, которое оно делится на 2 как целое число, с минимальным возможным количеством байтов. На входе будет ненулевое целое число (любое положительное или отрицательное значение в пределах вашего языка).
Тестовые случаи:
14 -> 1
20 -> 2
94208 -> 12
7 -> 0
-4 -> 2
Ответ с наименьшим количеством байтов выигрывает.
Совет: попробуйте преобразовать число в основание 2. Посмотрите, что это говорит вам.
The input will be a nonzero integer
Нужно ли редактировать это после вашего комментария о том, что ноль является потенциальным входом?Ответы:
Желе , 4 байта
В последней версии Jelly,
ÆEḢ
(3 байта) работает.Попробуй это здесь .
источник
машинный код x86_64, 4 байта
Инструкция BSF (bit scan forward) делает именно это !
В сборке в стиле gcc это:
Входные данные передаются в регистр EDI и возвращаются в регистр EAX в соответствии со стандартными 64-битными соглашениями о вызовах c .
Из-за двоичного кодирования, дополняющего два, это работает как для чисел -ve, так и для чисел + ve.
Кроме того, несмотря на документацию, в которой говорится «Если содержимое исходного операнда равно 0, содержимое целевого операнда не определено». На моей виртуальной машине Ubuntu я обнаружил, что вывод
f(0)
равен 0.Инструкции:
evenness.s
и соберитеgcc -c evenness.s -o evenness.o
evenness-main.c
и скомпилируйте сgcc -c evenness-main.c -o evenness-main.o
:Затем:
gcc evenness-main.o evenness.o -o evenness
./evenness
@FarazMasroor попросил более подробную информацию о том, как этот ответ был получен.
Я больше знаком с c, чем со сложностями сборки x86, поэтому обычно я использую компилятор для генерации кода сборки для себя. Я знаю по опыту , что НКУ расширение , такие как
__builtin_ffs()
,__builtin_ctz()
и__builtin_popcount()
как правило , компилировать и смонтируют 1 или 2 инструкции по x86. Итак, я начал с функции c, например:Вместо того чтобы использовать обычную компиляцию gcc вплоть до объектного кода, вы можете использовать
-S
опцию для компиляции только в сборку -gcc -S -c evenness.c
. Это дает файл сборкиevenness.s
следующим образом:Многое из этого можно сыграть в гольф. В частности, мы знаем, что соглашение о вызовах c для функций с сигнатурой приятно и просто - входной параметр передается в регистр, а возвращаемое значение возвращается в регистр. Таким образом, мы можем извлечь большинство инструкций - многие из них связаны с сохранением регистров и настройкой нового стекового фрейма. Здесь мы не используем стек и используем только регистр, поэтому не нужно беспокоиться о других регистрах. Это оставляет "гольф" код сборки:
int f(int n);
EDI
EAX
EAX
Обратите внимание, что, как указывает @zwol, вы также можете использовать оптимизированную компиляцию для достижения аналогичного результата. В частности,
-Os
производит точно такие же инструкции (с несколькими дополнительными директивами на ассемблере, которые не создают никакого дополнительного объектного кода).Теперь он собран
gcc -c evenness.s -o evenness.o
, который затем может быть связан с программой тестового драйвера, как описано выше.Есть несколько способов определить машинный код, соответствующий этой сборке. Мой любимый - использовать команду gdb
disass
disassembly:Итак, мы видим, что машинный код для
bsf
инструкции есть0f bc c7
и дляret
естьc3
.источник
evenness-main.c
с разными настройками оптимизации; для меня это ломает-O
,-O2
или-O3
.Python, 25 байт
n & -n
обнуляет все, кроме младшего значащего бита, например:Нас интересует число конечных нулей, поэтому мы преобразуем его в двоичную строку, используя
bin
для этого числа, которое будет указано выше"0b10000"
. Так как мы не заботимся ни о0b
, ни о1
, мы вычитаем 3 из этой длины строки.источник
Pyth, 6 байт
Попробуй это здесь .
источник
JavaScript (ES6), 18 байт
4 байта короче
31-Math.clz32
. Хах.источник
Math.clz32
тоже ...JavaScript ES6,
2219 байтПохоже, рекурсия - самый короткий маршрут.
источник
Pyth, 8 байт
Например, двоичное представление
94208
:После разбиения на
1
s и получения последнего элемента полученного массива это становится:Это 12 нулей, так что это "12-летняя четность".
Это работает, потому что,
x / 2
по сутиx >> 1
, это право на сдвиг битов1
. Следовательно, число делится на 2 только тогда, когда младший бит равен0
(точно так же, как десятичное число делится на 10, когда его последняя цифра равна0
).источник
05AB1E ,
45 байтТеперь поддерживает отрицательные числа. Код:
Попробуйте онлайн!
Объяснение:
Использует кодировку CP-1252.
источник
Pyth, 6 байт
В основном просто
источник
MATL , 5 байтов
Это работает для всех целых чисел.
Попробуйте онлайн!
источник
C, 36 (28) байтов
(Не проверяется нулевой аргумент, поскольку указан ненулевой аргумент.)
Обновление (в ответ на комментарий) : если мы разрешаем объявления функций в стиле K & R, то у нас может быть 28-байтовая версия:
В этом случае, мы рассчитываем на то , что компилятор по умолчанию , как
n
и тип возвращаемогоf
вint
. Эта форма генерирует предупреждение с C99, хотя и не компилируется как действительный код C ++.источник
int n
->n
это все еще действительный код C и обрезает 4 символа.Java 7, 39 или, может быть, 44 байта
Уу рекурсия! Мне пришлось использовать
!=
вместо более короткого сравнения, чтобы оно не переполнялось при отрицательном входе, но в остальном это довольно просто. Если это странно, отправьте ноль. Если даже, добавьте один и сделайте это снова.Есть две версии, потому что сейчас вывод на ноль неизвестен. Первый будет повторяться до тех пор, пока стек не переполнится, и ничего не выведет, потому что 0 бесконечно четно. Вторая выдает хороший, безопасный, но, вероятно, не математически строгий 0 для вывода.
источник
JavaScript (ES6),
20 байт,19 байт.Это порт решения Haskell от @nimi для JavaScript. Он использует свойства «короткого замыкания»,
&&
которые возвращают свою левую сторону, если она ложная (что в данном случае-0
), или возвращают правую сторону.odd x = 0
Поэтому для реализации мы делаем левую сторону,1 - (x % 2)
которая пузырится0
через&&
, в противном случае мы повторяем1 + f(x / 2)
.Бритье
1 - (x % 2)
as(~x) % 2
связано с @Neil, приведенным ниже, и обладает странным свойством, которое заставляет указанную выше функцию генерировать-0
маленькие нечетные числа. Это значение является особенностью решения JS о том, что целые числа являются двойниками IEEE754; эта система имеет отдельную+0
и-0
которые специально в JavaScript===
для друг друга.~
Оператор вычисляет 32-битную-знаково-целое побитовое инверсии для числа, что для малых нечетных чисел будет отрицательным четным числом. (Положительное число,Math.pow(2, 31) + 1
например, производит0
вместо-0
.) Странное ограничение для 32-битных целых чисел не имеет никаких других эффектов; в частности это не влияет на правильность.источник
~x&1
Байт короче, чем1-x%2
.Perl 6,
2318 байтиспользование
источник
Рубин 24 байта
Мой первый код подачи гольфа (да!)
Как я сюда попал :
Сначала я хотел получить код, который на самом деле соответствовал спецификации, чтобы решить мою проблему, поэтому я создал метод без учета количества байтов:
с этим знанием я отменил функцию в цикле while и добавил
$*
(ARGV) в качестве входных данных, а i - в счетчик того, сколько раз число было уменьшено вдвое, прежде чем оно станет нечетным.Я очень гордился этим и почти представил его, прежде чем мне показалось, что все это деление на два звучало для меня немного двоично, будучи инженером-программистом, но не ученым-программистом, это не было первым, что пришло мне в голову.
Итак, я собрал некоторые результаты о том, как выглядят входные значения в двоичном виде:
Я заметил, что результатом было количество позиций слева, которые мы должны пройти, прежде чем число станет нечетным.
Делая несколько простых манипуляций со строками, я разбил строку на последнее вхождение 1 и посчитал длину оставшихся 0:
используя
("%b" % x)
форматирование, чтобы превратить число в двоичное, и String # slice, чтобы разделить мою строку.Я узнал кое-что о рубине в этом квесте и с нетерпением жду новых гольфов!
источник
@wizzwizz4
в начале комментария, чтобы ответить мне. (Это работает со всемиJ, 6 байт
Объяснение:
источник
C 37 байт
f(int x){return x?x&1?0:1+f(x/2):0;}
Рекурсивно проверяйте последний бит, пока он не станет равным 0.источник
f(int n){return __builtin_ctz(n);}
если вы готовы использовать расширения GCC. Или даже#define f __builtin_ctz
int
. Это неявно, как и тип возвращаемого значения.f(n){...}
? GCC не скомпилирует это. Я не эксперт по Си, но быстрый поиск показывает, что, возможно, эта функция была удалена в более поздних версиях C. Так что, возможно, она будет компилироваться с соответствующими флагами?-ansi
или-gnu99
? Я знаю, что заставил это работать. Я написал подсказку, ответь об этом!Haskell, 28 байт
Пример использования:
f 94208
->12
.Если число нечетное, результат будет
0
, иначе1
плюс рекурсивный вызов с половиной числа.источник
div x 2
? Почему нетx/2
?div
целочисленное деление, деление с/
плавающей запятой.Befunge, 20
Выполнение кода продолжает двигаться вправо и переходить ко второму символу первой строки (благодаря завершающему
#
) до2%
выходных данных1
, что приводит_
к переключению направления влево, а затем|
вверх, что оборачивается во<
второй строке, какие выходы и выходы. Мы увеличиваем каждый второй элемент стека с начала до конца, а затем делим вершину на 2.источник
Сетчатка ,
2917Попробуйте онлайн!
2 байта сэкономлено благодаря Мартину!
Принимает одинарный ввод. Это многократно соответствует наибольшему количеству
1
s, которое может иметь, так что это число1
s точно соответствует остальным1
s в числе. Каждый раз, когда он делает это, он добавляет;
к строке. В конце мы подсчитаем количество;
s в строке.Если вы хотите десятичный ввод, добавьте:
к началу программы.
источник
Джольф, 6 байт
Попробуй это здесь!
Довольно просто ... Престижность ETHProductions для вытеснения Jolf с версией, которая действительно должна работать!
источник
PARI / GP, 17 байт
источник
6502 машинного языка, 7 байтов
Чтобы найти значение места младшего значащего 1 бита ненулевого значения в аккумуляторе, оставив результат в регистре X:
Чтобы запустить это на симуляторе 6502 на e-tradition.net , поставьте перед ним префикс
A9
8, а затем 8-разрядное целое число.Это разбирается на следующее:
Это эквивалентно следующему C, за исключением того, что C
int
должен быть как минимум 16-битным:То же самое работает на 65816, предполагая MX = 01 (16-разрядный аккумулятор, 8-разрядный индекс), и эквивалентно приведенному фрагменту Си.
источник
Брахилог ,
2715 байтобъяснение
источник
CJam, 8 байт
Читайте целое число, абсолютное значение, простое множитель, считайте двойки.
источник
JavaScript ES6, 36
38байтГольф два байта благодаря @ETHproductions
Довольно скучный ответ, но он делает свою работу. На самом деле может быть слишком похож на другой ответ, если он добавит предложенные изменения, то я удалю свой.
Для запуска назначьте его переменной (
a=>{for...
), так как это анонимная функция, а затем вызовите его с помощьюa(100)
.источник
b%2==0
может быть изменено наb%2-1
иc++
может быть перемещено в последнюю частьfor
оператора. Я думаю, что это также будет работать:b=>eval("for(c=0;b%2-1;b/=2)++c")
b%2-1
=>~b&1
Кроме того, я думаю, что это не сработает при вводе0
, что можно исправить с помощьюb&&~b&1
b%2-1
проверка не проходит для отрицательных нечетных чисел.ES6, 22 байта
Возвращает -1, если вы передаете 0.
источник
DUP , 20 байт
Try it here!
Преобразованный в рекурсию, вывод теперь является верхним числом в стеке. Использование:
объяснение
источник
Japt
95 байтПроверьте это онлайн!
Предыдущая версия должна была быть пятью байтами, но эта на самом деле работает.
Как это устроено
источник
C,
444038 36 байт2 байта, спасибо @JohnWHSmith . 2 байта, спасибо @luserdroog .
Тест живи на идеоне .
источник
!(n%2)
на маленький~n&1
.=0
. Глобальные переменные неявно инициализируются до 0.a
, разве она не гарантированно сработает при первом вызове? Я не знал, что было разрешено.