Mappage bijectif d'entiers à un nombre variable de bits

11

Un nombre variable de bits est un tableau de 0 ou plusieurs bits. Il en [0, 1]va de même pour un nombre variable de bits, mais il en est de même [].

Écrivez une fonction ou un programme qui, étant donné un entier non négatif, renvoie un nombre variable de bits de sorte que chaque entier ait un mappage un à un (bijectif) avec un tableau.

Il existe une quantité infinie de ces mappages, vous êtes libre d'en créer un à votre guise, mais ce doit être un à un. Votre mappage doit conceptuellement être un pour un pour un entier de taille arbitraire, mais c'est OK si votre implémentation échoue pour les grands entiers en raison des limites numériques des types dans votre langue préférée (par exemple, les C int).

À titre d'exemple de ce qui n'est pas un mappage un à un, il suffit de répertorier les chiffres binaires de l'entier. Dans un tel système, 5 devient [1, 0, 1](ou 0b101), mais ce n'est pas un à un, car 0b0101ou [0, 1, 0, 1]signifie également 5.

Il devrait être assez évident qu'un mappage n'est pas un à un s'il saute un entier (par exemple, il ne fonctionne pas pour 5), mais je tiens à préciser que sauter un tableau de bits variable n'est pas non plus un -à une. Vous devez mapper sur tous les tableaux de bits variables possibles, y compris [].


Le code le plus court en octets gagne.

orlp
la source
Pouvons-nous renvoyer une chaîne de 0 et de 1?
xnor
@xnor Oui, une chaîne de 0 et de 1 suffit.
orlp

Réponses:

4

Gelée, 3 octets

‘BḊ

Même idée que xnor: correspond 0 1 2 3 4 ...à [] [0] [1] [0 0] [0 1] ...; le code est fondamentalement increment → binary → remove first.

Essayez-le en ligne .

Lynn
la source
10

Python, 20 octets

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

Tester:

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

Faire lambda n:bin(n+1)[3:]incrémente l'entrée, puis prend la représentation binaire avec le premier symbole supprimé ( [3:]car le préfixe 0best deux caractères). Étant donné que tout nombre positif commence par 1 en binaire, cela donne uniquement une représentation binaire.

Un octet est enregistré en utilisant à la place le complément de bits ~npour obtenir la négation -(n+1)et en supprimant le signe négatif en coupant un symbole de plus.

xnor
la source
1
Inverse: lambda s:int('1'+s,2)-1.
orlp
2

Pyth, 5 octets

t.BhQ

Simplement une traduction de la réponse de xnor en Pyth.

Qest eval () 'd input (), l' hincrémente, le .Bconvertit en une chaîne binaire et tprend la "queue" (qui est tout sauf le premier caractère).

Poignée de porte
la source
2

Haskell, 41 38 30 29 octets

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

Exemple d'utilisation: (l!!) 4-> "10".

En commençant par la liste vide comme premier élément, parcourez la liste paresseusement et ajoutez l'élément actuel avec 0et avec 1devant.

Modifier: @xnor a enregistré 3 11 octets. Merci!

nimi
la source
Idée intéressante. La fonction itérée peut être écrite[(0:),(1:)]<*>
xnor
@xnor: Oh, tu m'as déjà montré le <*>truc, mais je l'ai oublié. Merci encore!
nimi
Ooh, vous pouvez définir toute la liste paresseusement: l=[]:[b:x|x<-l,b<-[0,1]];(l!!).
xnor
@xnor: Super! Merci beaucoup! Oh, le passage aux chaînes enregistre un octet de plus.
nimi
Je pense qu'il devrait y avoir un moyen plus court d'exprimer [b:x|x<-l,b<-"01"]avec un produit ou une carte de concaténation, mais l'expression du produit (:)<$>[0,1]<*>lva dans le mauvais ordre, en ajoutant d'abord 0 à tout, jamais à 1 car la liste est infinie. As tu des idées?
xnor
1

JavaScript (ES6), 29 octets

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

Même idée que xnor.

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

andlrc
la source
Ceci est facilement étendu à d'autres bases selon codegolf.stackexchange.com/q/78990
Neil
1

Jolf, 4 octets

Essayez-le ici!

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

Stratégie très simple, se trouve également être la plus courte.

Conor O'Brien
la source
1

Haskell, 35 octets

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

Haskell n'a pas de binaire intégré, donc la conversion (inversée) se fait manuellement. Pour supprimer le 1 initial, le cas de base s'est 1transformé en liste vide.

Edit: enregistré un octet en conjuguant à la +1place.

h 0=[]
h m=1-mod m 2:h(div(m+1)2-1)
xnor
la source
1

C, 40 octets

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

Convertit l'entrée en base bijective 2 (avec symboles 0et 1), comme les autres réponses.

idéone it!

un nom mince contracté
la source