Білективне відображення від цілих чисел до змінної кількості бітів


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

Пітон, 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.

Qє eval () 'd input (), hзбільшує його, .Bперетворює його у двійкову рядок і tприймає "хвіст" (що є все, крім першого символу).


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: Чудово! Дуже дякую! О, перемикання на рядки економить ще один байт.
німі

Я відчуваю, що повинен бути якийсь коротший спосіб виразити [b:x|x<-l,b<-"01"]продукт або конкату-карту, але вираз продукту (:)<$>[0,1]<*>lйде в неправильному порядку, спочатку попередньо додавши 0 до всього, ніколи не потрапляючи до 1, оскільки список нескінченний. У вас є ідеї?
xnor



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.