Чтобы найти цифровую жесткость целого числа, возьмите его двоичное представление и посчитайте, сколько раз можно удалить как начальный, так и конечный
1
символы, пока он не начнется или не закончится знаком a0
. Общее количество удаленных бит - это его цифровая твердость.
Это довольно многословное объяснение - поэтому давайте разберем его с проработанным примером.
Для этого примера мы будем использовать число 3167. В двоичном виде это:
110001011111
(Обратите внимание, что во время преобразования в двоичный файл вы должны убрать начальные нули)
Он не начинается и не заканчивается 0
, поэтому мы удаляем 1 пару битов:
1 1000101111 1
И другой:
11 00010111 11
Но теперь в начале есть 0, поэтому мы не можем больше удалять 1
пары. Всего мы удалили 4 бита, и поэтому 4 - это цифровая жесткость 3167.
Однако для чисел, которые можно записать как 2 n -1 для положительного n (то есть содержать только 1
в двоичном представлении), 0 никогда не будет достигнуто, и поэтому все биты могут быть удалены. Это означает, что твердость - это просто длина целого бита.
Соревнование
Ваша задача - написать программу или функцию, которая, учитывая неотрицательное целое число n >= 0
, определяет его цифровую твердость.
Вы можете отправить полную программу, которая выполняет ввод / вывод, или функцию, которая возвращает результат. Ваше представление должно работать для значений в n
пределах стандартного целочисленного диапазона вашего языка.
Тестовые случаи
Пожалуйста, сообщите мне, если какой-либо из них является неправильным, или если вы хотите предложить какие-либо крайние случаи для добавления.
0 -> 0
1 -> 1
8 -> 0
23 -> 2
31 -> 5
103 -> 4
127 -> 7
1877 -> 2
2015 -> 10
Вот отличное решение Python, которое я использовал для генерации этих тестовых случаев (не гарантировано, что они не содержат ошибок):
def hardness(num) -> int:
binary = bin(num)[2:]
if binary.count('0') == 0:
return num.bit_length()
revbin = binary[::-1]
return min(revbin.find('0'), binary.find('0')) * 2
1
возвращает 1, когда0
в нем вообще нет? Я имею в виду, вы не можете удалить достаточно 1 из строки, чтобы она начала или заканчивалась0
.Ответы:
Желе ,
1110 байтПопробуйте онлайн!
Как это работает
источник
Python ,
76696863626057 байтПопробуйте онлайн!
Как это работает
Это рекурсивное решение, которое принимает вход n и продолжает увеличивать k - начиная с 0 - в то время как LSB k (n) (бит с индексом k справа) и MSB k (n) (бит с индексом k слева) установлены. По окончании возвращает k, если все биты n установлены, и 2k, если нет.
Давайте начнем с переписывания лямбда- функции f как именованной функции F со вспомогательной переменной t .
В каждом вызове F мы сначала сдвигаем бит n всего на k единиц вправо и сохраняем результат в t . Таким образом, LSB 0 (t) = LSB k (n) , поэтому t нечетно тогда и только тогда, когда установлен LSB k (n) .
Определение, установлен ли MSB k (n) , немного сложнее; это то, что
n & t > t >> 1
достигается. Чтобы проиллюстрировать, как это работает, давайте рассмотрим целое число n = 1αβγδεζη 2 длиной 8 бит и проанализируем вызов функции F (n, 3) , т. Е. K = 3 .Мы пытаемся определить, установлено ли значение MSB 3 (n) = γ , изучая истинное значение сравнения (n & t> t >> 1) = (1αβγδεζη 2 & 1αβγδ 2 > 1αβγ 2 ) . Давайте рассмотрим задействованные целые числа.
Мы утверждаем, что γ = 1 тогда и только тогда, когда n & t> t >> 1 .
Если γ = 1 , то n & t имеет битовую длину 5, а t >> 1 имеет битовую длину 4 , поэтому n & t> t >> 1 .
Это доказывает, что γ = 1 влечет n & t> t >> 1 .
Если n & t> t >> 1 , есть два варианта: либо γ = 1, либо γ = 0 . В первом случае доказывать нечего.
Во втором случае имеем, что αβγδ 2 ≥ n & t> t >> 1 = 1αβγ 2 .
Поскольку αβγδ 2 > 1αβγ 2 , мы должны иметь MSB 0 (αβγδ 2 ) ≥ MSB 0 (1αβγ 2 ) , что означает, что α = 1 .
Таким образом, 1βγδ 2 > 11βγ 2 , поэтому мы должны иметь MSB 1 (1βγδ 2 ) ≥ MSB 1 (11βγ 2 ) , что означает, что β = 1 .
В свою очередь это означает, что 11γδ 2 > 111γ 2 . Вспоминая, что γ = 0 во втором случае, мы получаем неравенство 110δ 2 > 1110 2 , которое неверно, поскольку MSB 2 (110δ 2 ) = 0 <1 = MSB 2 (1110 2 ) .
Таким образом, возможен только первый случай, и n & t> t >> 1 влечет γ = 1 .
Подводя итог, если установлены и LSB k (n), и MSB k (n) , t будет нечетным, а n & t> t >> 1 будет истинным , поэтому t & (n & t> t >> 1) будет выход 1 . Однако, если LSB k (n) или MSB k (n) не установлены (или если и то и другое), t будет четным или n & t> t >> 1 будет False , поэтому t & (n & t> t> > 1) даст 0 .
Вызов F с одним аргументом инициализирует k = 0 . В то время как условие, которое мы обсуждали ранее, выполняется, выполняется код after
and
, который (среди прочего) рекурсивно вызывает F с увеличенным k .Как только LSB k (n) или MSB k (n) не установлены, условие не выполняется, и F (n, k) возвращает 0 . Каждый из предыдущих вызовов функции k добавляет (n & (n + 1)> 0) + 1 к F (n, k) = 0 , поэтому F (n) возвращает ((n & (n + 1)> 0) + 1) к .
Теперь, если все биты n равны (то есть, если n равно 0 или все его биты установлены), n + 1 не будет иметь каких-либо общих битов с n , поэтому n & (n + 1) = 0 и F (n) возвращает k . Однако, если n имеет как установленные, так и не установленные биты, n & (n + 1)> 0 и F (n) возвращает 2k .
источник
input()
,while
иprint
уже 17 байтов ...MATL ,
1312 байтПопробуйте онлайн! Или проверьте все тестовые случаи .
объяснение
Код повторяет каждую двоичную цифру и подсчитывает, сколько раз можно удалить две внешние цифры.
источник
Python, 82 байта
Я чувствую, что все еще можно играть в гольф, но я потратил некоторое время, пробуя разные методы, и это был самый короткий путь.
Попробуйте онлайн
Хотя это работает аналогично программе Python для OP, я создал ее до того, как вопрос был опубликован, после просмотра вопроса в Песочнице, в которой не было такой программы.
источник
Python 2, 66 байт
Разбивает двоичное представление входных данных на порции 1. Подсчитывает количество единиц в меньшем из первого и последнего чанка, затем удваивает его, если только в одном чанке этот счет не удвоится.
источник
PowerShell ,
109106 байтПопробуйте онлайн!
Принимает вход
$args[0]
, использует вызов .NET дляconvert
негоtoString
с базой2
(то есть, сделать его бинарное), то-split
S , что строка на0
с, магазины, в$a
. Важно отметить: вызов .NET не возвращает начальные нули, поэтому первая цифра всегда a1
.Таким образом, существует две возможности - двоичная строка - все единицы, или был хотя бы один ноль. Мы различаем людей с псевдо-троичным индексом
$a.count-eq1
. Если в двоичном файле есть хотя бы один ноль, то в левом случае мы берем минимальную длину первой[0]
строки1
s и последней[-1]
строки (найденных|sort
и затем[0]
). Чем короче из них, тем больше пар мы можем удалить, поэтому мы умножаем это на2
. Обратите внимание, что если исходная двоичная строка оканчивается на a0
, как для ввода8
, то[-1].length
также будет0
(так как это пустая строка), что при умножении на2
равно0
.В противном случае, с двоичной строкой, все мы берем just
$b
(которая ранее была задана равной длине первой[0]
строки, в данном случае, всей двоичной строке).В любом случае этот результат остается в конвейере, а вывод неявным.
источник
JavaScript (ES6), 57 байт
Принимает двоичный файл и пытается сопоставить все
1s
или, в случае неудачи, равное количество ведущих и конечных1s
.источник
Сетчатка , 48 байт
Попробуйте онлайн
Объяснение:
источник
C #, 133 байта
Функция, которая возвращает твердость. Берет целое число из аргумента.
Ну а сегодня я узнал
'1' + '1' = 98
в C #.источник
'1'
, что ASCII char 49, а 49 + 49 = 98.1 + 1 = 2
не работает. @FlipTackC
898885 байтСохранено два байта из-за @FlipTack, указывающего на бесполезное объявление.
Вызов
f()
с номером для проверки, выход возвращается из функции.Попробуйте это на Ideone .
источник
JavaScript (ES6),
5958 байтКонтрольные примеры
Показать фрагмент кода
источник
Желе , 14 байт
Попробуйте онлайн!
источник
C,
1371321221191171149894928785 байтВремя начать играть в гольф B-)
Вот доказательство
и вывод;
источник
Java (OpenJDK) ,
181156150 байтПопробуйте онлайн!
источник
Mathematica,
6356 байтобъяснение
Сгенерировать представление base-2 для ввода, заключенное в
List
. Храните это вl
Если элемент min
l
равен 1, выведите 1. Если нет, выведите 2. Умножьте это на ...Разделить
l
на трассы.Возьмите первый и последний элемент.
Возьмите сумму обоих.
Найдите меньшее между двумя.
(Умножьте первый результат (1 или 2) на этот результат).
источник
Октава,
5654 байтаПопробуйте онлайн!
Объяснение:
двоичное представление
n
Возьмите кумулятивный мин
d
и кумулятивный мин перевернулd
сделать матричное умножение
умножить на 2, если все цифры 1;
источник
Pyth, 18 байт
Программа, которая принимает ввод целого числа и печатает результат.
Набор тестов (Первая строка для форматирования)
Как это работает
источник
APL, 26 байт
Тестовые случаи:
Объяснение:
источник
J, 22 байта
Это основано на аккуратном приеме, извлеченном из этой задачи .
Попробуйте онлайн!
объяснение
источник
PHP,
8374 байта3 + 6 байтов, сохраненных Йоргом
принимает данные от STDIN; беги с
-nR
.сломать
источник
<?=~($s=decbin($argn))[$a=strspn($s,1)]?2*min($a,strspn(strrev($s),1)):$a;
JavaScript (ES6), 83 байта
Ungolfed:
источник
Mathematica, 62 байта
Чистая функция где
#
представляет первый аргумент.(h=0;...;h)&
устанавливаетh=0
, делает кучу вещей...
, затем возвращаетh
(твердость). Давайте посмотрим на кучу вещей:Спасибо Грегу Мартину за то, что познакомил меня с этим трюком .
источник
Haskell ,
9492 байтаПопробуйте онлайн! Использование:
Объяснение:
b
преобразует число в двоичное и возвращает список нулей и единиц с младшим битом первым. Вh
, этот список инвертируется и поэлементно умножается на исходный список, а затемspan(>0)
разделяется после начальных1
s:Результирующий кортеж сопоставляется с шаблоном,
(c,_:_)
где_:_
совпадает с любым непустым списком, поэтомуc = [1,1]
. Поскольку байты удаляются спереди и сзади,c++c = [1,1,1,1]
возвращаются и, наконец, суммируются, чтобы получить цифровую жесткость .Если второй список кортежа пуст, то двоичное представление содержит только единицы, а число единиц - цифровая жесткость. При неудачном сопоставлении с образцом
h
возвращается простоn
, что снова суммируется.источник
Perl 61 байт
Суть этого выражения
/^(1+).*\1$/
в$1
том, что ответом в 2 раза больше длины . Остальная часть кода является служебной и связана с особым случаем всего 1.источник
sprintf
аргументов. Кроме того, использование-p
флага позволит вам написать полную программу, которая будет короче, чем ваша функция, так как вы сможете ее опуститьsub f{...}
(вместо этого вам придётся заканчивать,$_=...
но это всё равно улучшение на 4 байта). Наконец-то вместоlength(...)
тебя можно сделать/0/&&s/^(1+).*\1$/$1$1/;$_=y///c
. Это должно привести вас к 51 байту.PHP, 65 байт
Онлайн версия
источник
CJam, 14 байтов
Объяснение:
источник