การแมป Bijective จากจำนวนเต็มถึงจำนวนตัวแปรของบิต


11

จำนวนตัวแปรบิตคืออาร์เรย์ 0 หรือมากกว่าบิต ดังนั้น[0, 1]เป็นจำนวนตัวแปรของบิต []แต่เพื่อให้เป็น

เขียนฟังก์ชั่นหรือโปรแกรมที่ได้รับจำนวนเต็ม nonnegative ส่งกลับจำนวนตัวแปรของบิตเช่นว่าทุกจำนวนเต็มมีการทำแผนที่แบบหนึ่งต่อหนึ่ง (bijective) กับอาร์เรย์

มีการแมปดังกล่าวไม่ จำกัด จำนวนคุณมีอิสระที่จะสร้างได้ตามที่คุณต้องการ แต่ต้องเป็นแบบหนึ่งต่อหนึ่ง การทำแผนที่ของคุณต้องเป็นแนวคิดแบบหนึ่งต่อหนึ่งสำหรับจำนวนเต็มที่มีขนาดโดยพลการ แต่การดำเนินการของคุณจะล้มเหลวสำหรับจำนวนเต็มขนาดใหญ่เนื่องจากข้อ จำกัด ของประเภทตัวเลขในภาษาที่คุณต้องการ (เช่นของ C int)

ตัวอย่างของสิ่งที่ไม่ใช่การแม็พแบบหนึ่งต่อหนึ่งคือการแสดงรายการเลขฐานสองของจำนวนเต็ม ในระบบ 5 ดังกล่าวจะกลายเป็น[1, 0, 1](หรือ0b101) แต่ไม่ใช่แบบหนึ่งต่อหนึ่งเพราะ0b0101หรือ[0, 1, 0, 1]ยังหมายถึง 5

ควรชัดเจนว่าการแมปไม่ใช่แบบหนึ่งต่อหนึ่งหากข้ามจำนวนเต็ม (เช่นไม่ทำงาน 5) แต่ฉันต้องการทำให้ชัดเจนว่าการข้ามอาเรย์บิตตัวแปรไม่ใช่หนึ่งเดียว -to- หนึ่ง []คุณต้องแผนที่ไปยังอาร์เรย์ตัวแปรทุกบิตเป็นไปได้รวมถึง


รหัสที่สั้นที่สุดในหน่วยไบต์ชนะ


เราจะคืนสตริงเป็น 0 และ 1 ได้ไหม
xnor

@xnor ใช่สตริงของ 0s และ 1s นั้นใช้ได้
orlp

คำตอบ:


4

เยลลี่ 3 ไบต์

‘BḊ

แนวคิดเดียวกันกับ xnor: maps 0 1 2 3 4 ...to [] [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


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: โอ้คุณแสดงให้ฉันเห็น<*>เคล็ดลับก่อนหน้านี้ แต่ฉันลืมมัน ขอบคุณอีกครั้ง!
nimi

คุณสามารถกำหนดรายการทั้งหมดได้อย่างอิสระ: 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
Neil


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)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.