f=lambda n,k=1:`k`in bin(n^n/2)and-~f(n,k*10)
Попробуйте онлайн!
Как это работает
Используя XOR n и n / 2 (деление на 2, по существу, обрезает последний бит), мы получаем новое целое число m, чьи неустановленные биты указывают на совпадение соседних битов в n .
Например, если n = 1337371 , мы имеем следующее.
n = 1337371 = 101000110100000011011₂
n/2 = 668685 = 10100011010000001101₂
m = 1989654 = 111100101110000010110₂
Это уменьшает задачу, чтобы найти самый длинный пробег нулей. Поскольку двоичное представление положительного целого числа всегда начинается с 1 , мы попытаемся найти самую длинную 10 * строку цифр, которая появляется в двоичном представлении m . Это можно сделать рекурсивно.
Инициализируйте k как 1 . Каждый раз, когда выполняется f , мы сначала проверяем, появляется ли десятичное представление k в двоичном представлении m . Если это так, мы умножаем k на 10 и снова вызываем f . Если это не так, код справа от and
не выполняется, и мы возвращаем False .
Для этого мы сначала вычислим bin(k)[3:]
. В нашем примере bin(k)
возвращает '0b111100101110000010110'
, и 0b1
в начале удаляется с [3:]
.
Теперь -~
рекурсивный вызов before увеличивает значение False / 0 один раз для каждого вызова f рекурсивно. Если 10 {j} ( 1 за которым следуют j повторений по 0 ) не появятся в двоичном представлении k , самый длинный ряд нулей в k будет иметь длину j - 1 . Поскольку j - 1 последовательных нулей в k указывают j, совпадающих с соседними битами в n , желаемый результат равен j , что мы и получаем, увеличивая значение False / 0в общей сложности J раз.