Биективное отображение из целых чисел в переменное число бит

11

Переменное число битов - это массив из 0 или более битов. Так [0, 1]же, как и переменное число битов, но это так [].

Напишите функцию или программу, которая, учитывая неотрицательное целое число, возвращает переменное число битов, так что каждое целое число имеет однозначное (биективное) отображение с массивом.

Существует бесконечное количество таких отображений, вы можете создавать их по своему усмотрению, но они должны быть взаимно однозначными. Ваше отображение должно быть концептуально однозначным для целого числа произвольного размера, но это нормально, если ваша реализация терпит неудачу для больших целых чисел из-за числовых ограничений типов в вашем предпочтительном языке (например, C int).

В качестве примера того, что не является взаимно-однозначным отображением, просто перечисляем двоичные цифры целого числа. В такой системе 5 становится [1, 0, 1](или 0b101), но это не один к одному, потому что 0b0101или [0, 1, 0, 1]также означает 5.

Должно быть совершенно очевидно, что отображение не является взаимно однозначным, если оно пропускает целое число (например, оно не работает для 5), но я хотел бы прояснить, что пропуск массива переменных битов также не -к одному. Вы должны отобразить все возможные переменные битовые массивы, в том числе [].


Самый короткий код в байтах побеждает.

orlp
источник
Можем ли мы вернуть строку из 0 и 1?
xnor
@xnor Да, строка 0 и 1 в порядке.
orlp

Ответы:

4

Желе, 3 байта

‘BḊ

Та же идея, что и у xnor: отображается 0 1 2 3 4 ...на [] [0] [1] [0 0] [0 1] ...; код в основном increment → binary → remove first.

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

Линн
источник
10

Python, 20 байт

lambda n:bin(~n)[4:]

Тест:

>> [bin(~n)[4:] for n in range(16)]
['', '0', '1', '00', '01', '10', '11', '000', '001', '010', '011', '100', '101', '110', '111', '0000']

Выполнение lambda n:bin(n+1)[3:]увеличивает входные данные, затем принимает двоичное представление с удаленным первым символом ( [3:]потому что префикс 0bсостоит из двух символов). Поскольку любое положительное число начинается с 1 в двоичном виде, это однозначно дает двоичное представление.

Байт сохраняется вместо использования битового дополнения ~nдля получения отрицания -(n+1)и удаления отрицательного знака путем обрезания еще одного символа.

XNOR
источник
1
Inverse: lambda s:int('1'+s,2)-1.
orlp
2

Pyth, 5 байт

t.BhQ

Просто перевод ответа xnor на Pyth.

Qis eval () 'd input (), hувеличивает его, .Bпреобразует в двоичную строку и tберет "tail" (то есть все, кроме первого символа).

Дверная ручка
источник
2

Haskell, 41 38 30 29 байт

l="":[b:x|x<-l,b<-"01"]
(l!!)

Пример использования: (l!!) 4-> "10".

Начиная с пустого списка в качестве первого элемента, лениво пройдитесь по списку и добавьте текущий элемент с 0и 1перед ним.

Редактировать: @xnor сохранил 3 11 байтов. Благодаря!

Ними
источник
Интересная идея. Повторная функция может быть написана[(0:),(1:)]<*>
xnor
@xnor: О, ты показал мне <*>трюк раньше, но я забыл об этом. Еще раз спасибо!
Ним,
О, вы можете определить весь список лениво: l=[]:[b:x|x<-l,b<-[0,1]];(l!!).
xnor
@xnor: Отлично! Большое спасибо! О, переключение на строки экономит еще один байт.
Nimi
Я чувствую, что должен быть какой-то более короткий способ выразить [b:x|x<-l,b<-"01"]продукт или concat-map, но выражение продукта (:)<$>[0,1]<*>lидет в неправильном порядке, сначала добавляя 0 ко всему, никогда не доходя до 1, потому что список бесконечен. Есть ли у вас какие-либо идеи?
xnor
1

JavaScript (ES6), 29 байт

x=>(~x).toString(2).slice(2)

Та же идея, что и у Xnor.

f=x=>(~x).toString(2).slice(2);
[...Array(100)].map((v,x)=>A.textContent+=x + ': ' + f(x) + '\n')
<pre id=A></pre>

andlrc
источник
Это легко распространяется на другие базы в соответствии с codegolf.stackexchange.com/q/78990
Нейл
1

Джольф, 4 байта

Попробуй это здесь!

wBhj
  hj  input + 1
 B    converted to binary
w     with first removed.

Очень простая стратегия, также бывает самой короткой.

Конор О'Брайен
источник
1

Haskell, 35 байт

h 1=[]
h n=mod n 2:h(div n 2)
h.(+1)

Haskell не имеет встроенного двоичного кода, поэтому (обратное) преобразование выполняется вручную. Чтобы удалить начальную 1, базовый случай должен 1преобразоваться в пустой список.

Изменить: сохранить байт путем сопряжения +1вместо.

h 0=[]
h m=1-mod m 2:h(div(m+1)2-1)
XNOR
источник
1

C, 40 байтов

f(n){if(++n/2)putchar(n%2+48),f(n/2-1);}

Преобразует ввод в биективное основание 2 (с символами 0и 1), как и другие ответы.

Идеон это!

сокращенное существительное
источник