从整数到可变位数的双射映射


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 2016年

Answers:


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),并通过砍掉另一个符号来消除负号。


1
逆:lambda s:int('1'+s,2)-1
orlp 2016年

2

Pyth,5个字节

t.BhQ

只是xnor答案的翻译成Pyth。

Q是eval()的input(),对其进行h递增,.B将其转换为二进制字符串,并t采用“ tail”(除第一个字符外的所有字符)。


2

Haskell,41 38 30 29字节

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

用法示例:(l!!) 4-> "10"

从空列表开始作为第一个元素,懒洋洋地浏览列表,然后在当前元素之前加上01

编辑:@xnor保存3 11字节。谢谢!


有趣的主意。可以编写迭代函数[(0:),(1:)]<*>
xnor

@xnor:哦,您<*>之前给我看了把戏,但是我忘了。再次感谢!
nimi 2016年

哦,您可以延迟定义整个列表: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

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)

1

C,40个字节

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

像其他答案一样,将输入转换为双射基数2(带有符号01)。

ideone吧!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.