Чередование размазывания

12

Вступление

Эта задача требует от вас установить конечные нули двоичного представления целых чисел 010101…, это лучше всего объяснить на примере:

Учитывая целое число 400, первый шаг должен преобразовать это в двоичный файл:

110010000

Как мы видим, пятый бит является наименее значимым 1битом, поэтому начиная с него мы заменяем младшие нули на 0101:

110010101

Наконец, мы конвертируем это обратно в десятичное: 405

Вызов

Дано целое положительное число вернуть / вывести соответствующее результирующее значение определенного выше процесса.

правила

  • Эта последовательность определена только для целых чисел хотя бы с одним 1битом, поэтому входное значение всегда будет ≥ 1
  • Вы можете взять ввод в виде строки, список цифр (десятичных) вместо
  • Вам не нужно обрабатывать неверные данные

Testcases

Вот еще несколько тестов с промежуточными шагами (их не нужно распечатывать / возвращать):

In -> … -> … -> Out
1 -> 1 -> 1 -> 1
2 -> 10 -> 10 -> 2
3 -> 11 -> 11 -> 3
4 -> 100 -> 101 -> 5
24 -> 11000 -> 11010 -> 26
29 -> 11101 -> 11101 -> 29
32 -> 100000 -> 101010 -> 42
192 -> 11000000 -> 11010101 -> 213
400 -> 110010000 -> 110010101 -> 405
298 -> 100101010 -> 100101010 -> 298
ბიმო
источник
Можем ли мы принять 32-разрядное целое число?
Arnauld
@Arnauld: Конечно!
მოიმო
9
Некоторая идея игры в гольф: если nмаксимальная сила 2, которая делит вход, то ответ прост(input) + ceil((2^n - 2)/3)
JungHwan Мин

Ответы:

12

Python 3 , 20 байт

lambda n:(n&-n)//3+n

Попробуйте онлайн!

объяснение

Взять хотя 192бы пример. Его двоичная форма есть 11000000, и нам нужно преобразовать его в 11010101.

Отметим, что нам нужно добавить 10101к числу. Это геометрический ряд ( 4^0 + 4^1 + 4^2), который имеет замкнутую форму как (4^3-1)/(4-1). Это то же самое, что и 4^3//3где //обозначает целочисленное деление.

Если бы это было так 101010, то это все равно был бы геометрический ряд ( 2×4^0 + 2×4^1 + 2×4^2), что 2×4^3//3по причинам, указанным выше.

Во всяком случае, 4^3и 2×4^3будет просто наименее значимым битом, который мы получаем с помощью n&-n:

Мы замечаем, что дополнением nявляется 00111111. Если мы добавим один, он станет 01000000, и он будет перекрываться только с n=11000000самой младшей цифрой. Обратите внимание, что «дополнить и добавить один» это просто отрицание.

Дрянная Монахиня
источник
6
@ Mr.Xcoder хорошее спортивное мастерство
Leaky Nun
1
Возможно lambda n:(n&-n)//3+nтоже работает? Проходит все тестовые примеры , но, по моей интуиции, оно не должно быть действительным, верно?
Мистер Xcoder
@ Mr.Xcoder это действительно так.
Дрянная Монахиня
1
Почему бы не использовать Python 2 для сохранения байта? TIO
FlipTack
4
@FlipTack Я ненавижу Python 2
Лики Монахиня
8

Желе , 5 байт

&N:3+

Попробуйте онлайн!

На этот раз подход Лики Нун (по крайней мере, я немного помог ему в этом: P)

Желе , 7 байт

^N+4:6ạ

Попробуйте онлайн!

Использует фантастический подход JungHwan Мин при косвенной помощи от Мартина Эндера .

Мистер Xcoder
источник
Деннис опубликовал, а затем удалил очень похожее 5-байтовое решение сразу после того, как вы сделали это изменение. Нечто подобное &N:3|. Поздравляем; ты победил Денниса в желе! (Но не совсем вне игры в гольф.)
wizzwizz4
@ wizzwizz4 Я действительно мало что сделал, кроме того, что предложил небольшой гольф для подхода Лики, а затем портировал его. Но эх :-)
Mr. Xcoder
Это первый ответ Jelly только для ASCII, который я когда-либо видел.
MD XF
6

Wolfram Language (Mathematica) , 36 28 26 24 байта

-8 байтов благодаря @MartinEnder и -2 байта благодаря @ Mr.Xcoder

#+⌊(#~BitAnd~-#)/3⌋&

Попробуйте онлайн!

Нам нужно только найти число конечных нулей на входе, найти число с чередующимися 0s и 1s длиной на единицу меньше, и добавить его к входу.

Так, 400 -> 11001000 -> 110010000 + 0000 -> 110010101 + 101 -> 405

Явная формула для nчисла с чередованием 1s и 0s была дана в A000975 в OEIS. Мы можем использовать число nth, поскольку никакие два разных числа не могут иметь одинаковую длину в двоичном коде и иметь чередующиеся цифры.

Юнг Хван Мин
источник
1
2^#~IntegerExponent~2это(BitXor[#,#-1]+1)/2
Мартин Эндер
@MartinEnder вау! И тогда я могу просто объединить дроби, чтобы уменьшить количество байтов
JungHwan Мин
1
24 байта . Вы можете использовать #+⌊(#~BitAnd~-#)/3⌋&вместо этого.
г-н Xcoder
@ Mr.Xcoder отредактировано :)
JungHwan Мин
5

J , 19 18 байт

+(2|-.i.@#.-.)&.#:

Попробуйте онлайн!

Быстрое объяснение

Это старый ответ, но по природе он очень похож на текущий, он просто по-разному учитывает конечные нули. Смотрите комментарии для ссылки, объясняющей, как это работает.

+(2|i.@i.&1@|.)&.#:
                 #:  Convert to binary list
       i.&1@|.       Index of last 1 from right
            |.         Reverse
       i.&1            Index of first 1
    i.               Range [0, index of last 1 from right)
  2|                 That range mod 2
               &.    Convert back to decimal number
+                    Add to the input

Другие ответы:

Предыдущий ответ (19 байт).

+(2|i.@i.&1@|.)&.#:

Дольше, чем должно быть, потому что \идет справа налево.

+(2|#*-.#.-.)\&.(|.@#:)
капуста
источник
1
18 байт+(2|-.i.@#.-.)&.#:
миль
@miles возражают, объясняя, что там происходит с конверсией базы? Я предполагаю, что это как-то связано с нулями, но я не уверен.
Коул
#.~ подсчитывает количество конечных истин , поэтому нам нужно #.~ -. #:посчитать количество конечных нулей
миль
@ Мили Ах! Это очень, очень умно.
Коул
4

Юлия 0,6 , 12 байт

!n=n|n&-n÷3

Попробуйте онлайн!

Деннис
источник
Это похоже на эффективный метод, вы можете объяснить приоритет оператора? Например, я не могу сказать, оценивается ли он как ((!n=(n|n))&-n)/3, и !n=(((n|n)&(-n))/3)т. Д.
MD XF
В Джулии побитовые операторы имеют те же приоритеты, что и их арифметические аналоги, поэтому |он похож +и &похож *. Поэтому n|n&-n÷3разбирается как n | ((n&-n) ÷3).
Деннис
3

JavaScript (ES6), 40 39 байт

Принимает ввод как 32-разрядное целое число.

n=>n|((n&=-n)&(m=0xAAAAAAAA)?m:m/2)&--n

Контрольные примеры

Arnauld
источник
2

05AB1E , 13 8 5 байт

Сохранено 5 байтов благодаря аккуратной формуле Mr. Xcoder и JungHwan Min.
Сохранено еще 3 благодаря Mr. Xcoder.

(&3÷+

Попробуйте онлайн!

объяснение

(      # negate input
 &     # AND with input
  3÷   # integer divide by 3
    +  # add to input
Emigna
источник
1
Возможно, стоит упомянуть, что перенос ответа Mathematica дает вам 8 байтов
Mr. Xcoder
@ Mr.Xcoder: Ох, это аккуратная формула.
Emigna
1
Имеет ли 05ab1e побитовое И? Если это так, (<bitwise and here>3÷+должно работать на ~ 5 байтов.
г-н Xcoder
2

R , 71 58 байт

спасибо NofP за -6 байт

function(n){n=n%/%(x=2^(0:31))%%2
n[!cumsum(n)]=1:0
n%*%x}

Попробуйте онлайн!

Предполагается, что ввод является 32-разрядным целым числом. R в doubleлюбом случае имеет только 32-разрядные целые числа со знаком (приведение к нему происходит при переполнении целого числа) и 64-разрядные или беззнаковые целые числа отсутствуют.

Giuseppe
источник
Вы можете преобразовать в, which.max(n):1-1чтобы !cumsum(n)получить 65-байтовое решение
NofP
@NofP спасибо! Это отличная идея.
Джузеппе
2

брейкфук , 120 байт

>+<[[>-]++>[[>]>]<[>+>]<[<]>-]>[-<+>[-<[<]<]>]>[>]<[>+<[->+<]<[->+<]<]>>[<]+>[-[-<[->+<<+>]>[-<+>]]<[->++<]<[->+<]>>>]<<

Попробуйте онлайн!

Начинается со значения в текущей ячейке и заканчивается в ячейке с выходным значением. Очевидно, не будет работать с числами выше 255, поскольку это предел ячеек для типичного мозгового слуха, но сработает, если вы предполагаете бесконечный размер ячейки.

Джо Кинг
источник
1

PowerShell , 168 байт

param($n)$a=($c=[convert])::ToString($n,2);if(($x=[regex]::Match($a,'0+$').index)-gt0){$c::ToInt32(-join($a[0..($x-1)]+($a[$x..$a.length]|%{(0,1)[$i++%2]})),2)}else{$n}

Попробуйте онлайн!

Уч. Преобразование в / из двоичного кода и нарезка массивов не являются сильными сторонами PowerShell.

Вводит $nв виде числа. Мы немедленно convertотправляем двоичную базу 2и сохраняем ее в $a. Далее у нас есть конструкция if / else. Предложение if проверяет, имеет ли a значение regex Matchпротив 1 или более 0s в конце строки ( '0+$') indexв месте, большем чем 0(т. Е. В начале двоичной строки). Если это так, у нас есть с чем поработать, elseмы просто выводим число.

Внутри ifмы срезаем xпервые цифры и объединяем +их с оставшимися цифрами. Тем не менее, для оставшихся цифр мы перебираем их и вместо этого выбираем либо a, 0либо 1вывод, используя $i++%2для выбора. Это дает нам 010101...шаблон вместо 0s в конце. Затем мы -joinвозвращаем это обратно в строку и $cпревращаем обратно в Int32базу 2.

В любом случае число остается в конвейере и вывод неявен.

AdmBorkBork
источник
1

APL + WIN, 43 байта

p←+/^\⌽~n←((⌊1+2⍟n)⍴2)⊤n←⎕⋄2⊥((-p)↓n),p⍴0 1

Подсказки для ввода с экрана

Грэхем
источник
1

Python 3 , 56 байт

lambda n:eval((bin(n).rstrip("0")+"01"*n)[:len(bin(n))])

Попробуйте онлайн!

Пока не очень доволен этим, но я действительно не хотел использовать формулу ... -2 благодаря Роду . -1 спасибо Джонатану Фреху .

Мистер Xcoder
источник
eval(...)вместо того, int(...,2)чтобы сохранить байт.
Джонатан Фрех
1

JavaScript ES6, 13 байт

n=>(n&-n)/3|n

f = 
n=>(n&-n)/3|n
;
console.log (f(8));
console.log (f(243));
console.log (f(1048576));
console.log (f(33554432));

l4m2
источник
1

C, 56 байтов

i,k;f(n){for(k=i=1;n>>i<<i==n;k+=++i&1)k*=2;return n|k;}

Попробуйте онлайн!

C (gcc), 50 байтов

i,k;f(n){for(k=i=1;n>>i<<i==n;k+=++i&1)k*=2;k|=n;}

Попробуйте онлайн!

 51  48 байтов , используя решение Arnauld в :

Спасибо @ l4m2 за сохранение трех байтов!

m;f(n){return n|((n&-n)&(m=-1u/3*2)?m:m/2)&n-1;}

Попробуйте онлайн!

43 с gcc:

m;f(n){m=n|((n&-n)&(m=-1u/3*2)?m:m/2)&n-1;}

Попробуйте онлайн!

Steadybox
источник
0xAAAAAAAA=>-1u/3*2
l4m2
0

Желе , 13 байт

BŒgṪµ2Ḷṁ×CḄ+³

Попробуйте онлайн!

объяснение

Возьмем 24 в качестве примера ввода.

BŒgṪµ2Ḷṁ×CḄ+³
B                Binary representation of the input → 11000
 Œg              Group runs of equal length → [[1,1],[0,0,0]]
   Ṫ             Tail → [0,0,0]
    µ            New monadic link
     2Ḷ          [0,1] constant
       ṁ         Mold [0,1] to the shape of [0,0,0] → [0,1,0]
        ×        Multiply [0,1,0] by...
         C       1-[0,0,0]. If last bit(s) of the original input are 1 this will add nothing to the original input
          Ḅ      Convert to decimal from binary → 2
           +³    Add this with the original input → 26
dylnan
источник