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


11

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

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

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

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

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


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


Можем ли мы вернуть строку из 0 и 1?
xnor

@xnor Да, строка 0 и 1 в порядке.
orlp

Ответы:



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)и удаления отрицательного знака путем обрезания еще одного символа.


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>


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


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)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.