ฟังก์ชั่น Bijective ℤ→ℤⁿ


23

มันเป็นไปได้เล็กน้อยที่จะสร้างฟังก์ชัน bijectiveจาก (ชุดของจำนวนเต็มทั้งหมด) ถึง (เช่นฟังก์ชันตัวตน)ZZ

นอกจากนี้ยังสามารถสร้างฟังก์ชัน bijective จากถึง (ชุดของจำนวนเต็ม 2 คู่ทั้งหมด; ผลิตภัณฑ์คาร์ทีเซียนของและ ) ตัวอย่างเช่นเราสามารถใช้ lattice แทนคะแนนจำนวนเต็มบนระนาบ 2D วาดเกลียวจาก 0 ออกมาแล้วเข้ารหัสจำนวนเต็มคู่เป็นระยะทางตามแนวเกลียวเมื่อมันตัดกับจุดนั้นZZ2ZZ

เกลียว

(ฟังก์ชั่นที่ทำสิ่งนี้กับตัวเลขธรรมชาติเป็นที่รู้จักกันในชื่อฟังก์ชั่นการจับคู่ )

ในความเป็นจริงมีตระกูลของฟังก์ชัน bijective เหล่านี้:

fk(x):ZZk

ความท้าทาย

กำหนดตระกูลของฟังก์ชัน (โดยที่เป็นจำนวนเต็มบวก) กับคุณสมบัติที่ทำแผนที่เชิงเส้นจำนวนเต็มกับ -tuples ของจำนวนเต็มk(x)kk(x)k

การส่งของคุณควรจะได้รับปัจจัยการผลิตและกลับ(x)kxk(x)

นี่คือดังนั้นคำตอบที่สั้นที่สุดที่ถูกต้อง (วัดเป็นไบต์) ชนะ

ข้อมูลจำเพาะ

  • ครอบครัวใด ๆ สามารถใช้ได้ตราบใดที่มันเป็นไปตามเกณฑ์ข้างต้นk(x)
  • คุณได้รับการสนับสนุนให้เพิ่มคำอธิบายวิธีการทำงานของตระกูลฟังก์ชั่นของคุณรวมถึงตัวอย่างเพื่อคำนวณค่าผกผันของฟังก์ชัน (ซึ่งไม่รวมอยู่ในจำนวนไบต์ของคุณ)
  • เป็นเรื่องปกติถ้าฟังก์ชันผกผันไม่สามารถคำนวณได้ตราบใดที่คุณสามารถพิสูจน์ได้ว่าฟังก์ชันนั้นเป็น bijective
  • คุณสามารถใช้การแทนค่าที่เหมาะสมสำหรับจำนวนเต็มที่ลงนามและรายการจำนวนเต็มที่ลงนามแล้วสำหรับภาษาของคุณ แต่คุณต้องอนุญาตให้อินพุตจากฟังก์ชันของคุณถูก จำกัด ขอบเขต
  • คุณจะต้องรองรับค่าได้มากถึง 127 เท่านั้นk

มันโอเคที่จะใช้สตริงของkและxแทนที่จะเป็นจำนวนเต็มหรือไม่?
JungHwan Min

@JungHwanMin สตริงที่ใช้แทนตัวเลขอินพุตนั้นเป็นเรื่องปกติ
แยกผลไม้

คำตอบ:


19

อลิซ , 14 12 ไบต์

/O
\i@/t&Yd&

ลองออนไลน์!

ฟังก์ชันผกผัน (ไม่ใช่กอล์ฟ):

/o     Q
\i@/~~\ /dt&Z

ลองออนไลน์!

คำอธิบาย

Alice มี bijection ในตัวระหว่างถึง2ซึ่งสามารถคำนวณได้ด้วยY(unpack) และ inverse Z (pack) นี่คือข้อความที่ตัดตอนมาจากเอกสารที่อธิบายถึงความถูกต้อง

รายละเอียดของความน่าจะเป็นที่ไม่เกี่ยวข้องกับกรณีส่วนใหญ่ใช้ bijection จุดหลักคือให้ผู้ใช้เข้ารหัสสองจำนวนเต็มในหนึ่งและแยกจำนวนเต็มสองอีกครั้งในภายหลัง ด้วยการใช้คำสั่ง pack ซ้ำ ๆ รายการทั้งหมดหรือต้นไม้ของจำนวนเต็มสามารถเก็บไว้ในหมายเลขเดียว การทำแผนที่ที่คำนวณโดยการดำเนินการแพ็คเป็นฟังก์ชั่น bijective 2 →ℤ (เช่นการทำแผนที่แบบหนึ่งต่อหนึ่ง) อันดับแรกจำนวนเต็ม{... , -2, -1, 0, 1, 2, ... }ถูกแมปกับตัวเลขธรรมชาติ (รวมศูนย์) เช่น{... , 3, 1, 0, 2, 4 , ... }(กล่าวอีกนัยหนึ่งจำนวนเต็มลบจะถูกแมปกับเนเชอรัลคี่และจำนวนเต็มลบนั้นจะถูกแมปกับเนเชอรัลคู่) ตัวเลขธรรมชาติสองตัวจะถูกแมปกับหนึ่งผ่านฟังก์ชันการจับคู่คันทอร์ซึ่งเขียนธรรมชาติตามแนวทแยงมุมของจตุภาคแรกของตารางจำนวนเต็ม โดยเฉพาะ{(0,0), (1,0), (0,1), (2,0), (1,1), (0,2), (3,0), ... }คือ แมปไป{0, 1, 2, 3, 4, 5, 6, ... } จำนวนธรรมชาติที่เกิดขึ้นจะถูกแมปกลับไปที่จำนวนเต็มโดยใช้ค่าผกผันของค่าความยาวก่อน คำสั่ง unpack คำนวณสิ่งที่ตรงกันข้ามของการทำแผนที่นี้

ดังที่ได้กล่าวมาแล้วข้างต้นเราสามารถใช้การดำเนินการ unpack นี้เพื่อแมปถึงkเช่นกัน หลังจากนำไปใช้กับจำนวนเต็มเริ่มต้นเราสามารถนำจำนวนที่สองของผลที่ได้ออกมาอีกครั้งซึ่งจะให้รายการของสามจำนวนเต็ม ดังนั้นแอปพลิเคชันk-1ของจำนวนเต็มkYทำให้เราได้ผลลัพธ์

เราสามารถคำนวณค่าผกผันได้โดยการบรรจุรายการด้วยZจากท้ายสุด

ดังนั้นตัวโปรแกรมเองจึงมีโครงสร้างนี้:

/O
\i@/...d&

นี่เป็นเพียงเทมเพลตพื้นฐานสำหรับโปรแกรมที่อ่านจำนวนตัวแปรทศนิยมจำนวนเต็มเป็นอินพุตและพิมพ์หมายเลขตัวแปรตามผลลัพธ์ ดังนั้นรหัสที่แท้จริงคือ:

t   Decrement k.
&   Repeat the next command k-1 times.
Y   Unpack.

สิ่งหนึ่งที่ฉันต้องการพูดถึงคือ "ทำไมอลิซถึงมีบิวท์อินสำหรับbiject ℤ→ℤ 2 ในตัวภาษาอาณาเขตของการเล่นกอล์ฟนั้นไม่ใช่หรือ?" เช่นเดียวกับส่วนใหญ่ของอลิซประหลาดตัว -ins เหตุผลหลักคือหลักการออกแบบของอลิซว่าทุกคำสั่งมีสองความหมายหนึ่งสำหรับโหมดพระคาร์ดินัล (จำนวนเต็ม) และหนึ่งสำหรับโหมดลำดับ (สตริง) และทั้งสองความหมายที่ควรจะได้รับอย่างใดที่เกี่ยวข้องกับการให้ โหมด Cardinal และ Ordinal ให้ความรู้สึกว่าพวกเขาเป็นจักรวาลกระจกเงาที่ซึ่งสิ่งต่าง ๆ เหมือนกัน แต่ก็แตกต่างกัน และบ่อยครั้งที่ฉันมีคำสั่งสำหรับหนึ่งในสองโหมดที่ฉันต้องการเพิ่มจากนั้นจึงต้องหาคำสั่งอื่นที่จะจับคู่กับมัน

ในกรณีของYและZโหมด Ordinal มาก่อน: ฉันต้องการให้ฟังก์ชันแทรกสองสตริง (zip) และแยกพวกเขาอีกครั้ง (เปิดเครื่องรูด) คุณภาพของสิ่งนี้ที่ฉันต้องการบันทึกในโหมด Cardinal คือการสร้างจำนวนเต็มหนึ่งจากสองและสามารถที่จะแยกจำนวนเต็มสองจำนวนอีกครั้งในภายหลังซึ่งทำให้ bijection นั้นเป็นทางเลือกที่เป็นธรรมชาติ

ฉันคิดด้วยว่าสิ่งนี้จะมีประโยชน์อย่างมากนอกการเล่นกอล์ฟเพราะมันช่วยให้คุณเก็บรายการทั้งหมดหรือแม้แต่ต้นไม้จำนวนเต็มในหน่วยความจำเดียว (องค์ประกอบสแต็กเทปเซลล์หรือกริดเซลล์)


คำอธิบายที่ยอดเยี่ยมเช่นเคย
Luis Mendo

การค้นหาYและZในเอกสารของอลิซเป็นจริงสิ่งที่กระตุ้นให้ฉันโพสต์ความท้าทายนี้ (ฉันได้คิดเกี่ยวกับมันในขณะที่ แต่สิ่งนี้เตือนฉัน)
แยกผลไม้

11

Python, 96 93 ไบต์

def f(k,x):
 c=[0]*k;i=0
 while x:v=(x+1)%3-1;x=x//3+(v<0);c[i%k]+=v*3**(i//k);i+=1
 return c

หลักการนี้ใช้งานได้โดยการแปลงหมายเลขอินพุตxให้เป็นไตรภาคแบบสมดุลจากนั้นจึงกระจายความยาวน้อยที่สุดอย่างมีนัยสำคัญก่อนระหว่างพิกัดที่ต่างกันในรูปแบบโรบิน ดังนั้นสำหรับk=2ตัวอย่างเช่นทุก trit ตำแหน่งก็จะนำไปสู่การxประสานงานและทุก trit ตำแหน่งคี่จะนำไปสู่การyประสานงาน สำหรับk=3คุณจะต้องแรกที่สี่และที่เจ็ด trits ( ฯลฯ ... ) ที่เอื้อต่อxในขณะที่สองห้าแปดและนำไปสู่การและคนที่สามหกเก้าและนำไปสู่การyz

ตัวอย่างเช่นกับช่วยให้ดูที่k=2 x=35ในไตรภาคที่สมดุล35คือ110T(ใช้สัญลักษณ์ของบทความ Wikipedia ซึ่งTแสดงถึง-1หลัก) การแบ่งการทำทริสเรทติ้งจะให้1T(การทำทลายครั้งแรกและครั้งที่สามนับจากทางด้านขวา) สำหรับxพิกัดและ10(การทำสองและสี่) สำหรับyพิกัด 2, 3แปลงพิกัดแต่ละกลับไปทศนิยมที่เราได้รับ

แน่นอนว่าฉันไม่ได้แปลงจำนวนเต็มทั้งหมดให้เป็นไตรภาคแบบสมดุลทันทีในรหัส golfed ฉันแค่คำนวณหนึ่ง trit ทีละครั้ง (ในvตัวแปร) และเพิ่มมูลค่าลงในพิกัดที่เหมาะสมโดยตรง

นี่คือฟังก์ชันผกผัน ungolfed ที่รับรายการพิกัดและส่งกลับตัวเลข:

def inverse_f(coords):
    x = 0
    i = 0
    while any(coords):
        v = (coords[i%3]+1) % 3 - 1
        coords[i%3] = coords[i%3] // 3 + (v==-1)
        x += v * 3**i
        i += 1
    return x

fฟังก์ชั่นของฉันอาจโดดเด่นในเรื่องประสิทธิภาพ ใช้O(k)หน่วยความจำเท่านั้นและใช้O(k) + O(log(x))เวลาในการค้นหาผลลัพธ์จึงสามารถทำงานกับค่าอินพุตที่มีขนาดใหญ่มาก ลองf(10000, 10**10000)ยกตัวอย่างและคุณจะได้คำตอบในทันที (เพิ่มศูนย์พิเศษให้กับเลขชี้กำลังดังนั้นxจะ10**100000ใช้เวลา 30 วินาทีหรือมากกว่านั้นในพีซีเครื่องเก่าของฉัน) ฟังก์ชันผกผันนั้นไม่เร็วนักส่วนใหญ่เป็นเรื่องยากที่จะบอกเมื่อเสร็จสิ้น (มันจะสแกนพิกัดทั้งหมดหลังจากการเปลี่ยนแปลงแต่ละครั้งดังนั้นจึงต้องใช้O(k*log(x))เวลาพอสมควร) มันอาจได้รับการปรับให้เร็วที่สุด แต่อาจเร็วพอสำหรับพารามิเตอร์ปกติแล้ว


คุณสามารถลบช่องว่าง (ขึ้นบรรทัดใหม่) ภายใน while loop
Mr. Xcoder

ขอบคุณฉันคิดผิดพลาดว่ามีความขัดแย้งบางอย่างระหว่างลูปและการใช้;ข้อความลูกโซ่ในบรรทัดเดียว
Blckknght

9

Huskขนาด 10 ไบต์

§~!oΠR€Θݱ

ลองออนไลน์!

ฟังก์ชันผกผันก็มีขนาด 10 ไบต์เช่นกัน

§o!ȯ€ΠRΘݱ

ลองออนไลน์!

คำอธิบาย

ทิศทางไปข้างหน้า:

§~!oΠR€Θݱ  Implicit inputs, say k=3 and x=-48
        ݱ  The infinite list [1,-1,2,-2,3,-3,4,-4,..
       Θ    Prepend 0: [0,1,-1,2,-2,3,-3,4,-4,..
 ~    €     Index of x in this sequence: 97
§    R      Repeat the sequence k times: [[0,1,-1,..],[0,1,-1,..],[0,1,-1,..]]
   oΠ       Cartesian product: [[0,0,0],[1,0,0],[0,1,0],[1,1,0],[-1,0,0],[0,0,1],..
  !         Index into this list using the index computed from x: [-6,1,0]

ทิศทางย้อนกลับ:

§o!ȯ€ΠRΘݱ  Implicit inputs, say k=3 and y=[-6,1,0]
     ΠRΘݱ  As above, k-wise Cartesian product of [0,1,-1,2,-2,..
   ȯ€       Index of y in this sequence: 97
§o!         Index into the sequence [0,1,-1,2,-2,.. : -48

ผลิตภัณฑ์คาร์ทีเซียนในตัวΠทำงานได้ดีสำหรับรายการที่ไม่มีที่สิ้นสุดโดยแจกแจงแต่ละk -tuple หนึ่งครั้ง


[[0,1,-1,..],[[0,1,-1,..],[[0,1,-1,..]]ส่วนนี้ควรจะเป็น[[0,1,-1,..],[0,1,-1,..],[0,1,-1,..]]?
Erik the Outgolfer

@EriktheOutgolfer Umm ใช่แล้วคงแล้ว
Zgarb

นี่คือสิ่งที่สวยงาม ในฐานะโปรแกรมเมอร์ J คุณรู้หรือไม่ว่ามีวิธีที่ดีในการแปลงโซลูชันรายการที่ขี้เกียจแบบนี้เป็น J ซึ่งไม่สนับสนุนพวกเขา? ^:^:_วิธีแก้ปัญหาแบบพิมพ์มักจะยุ่งยากกว่าเดิมมาก ...
Jonah

@Jonah ฉันไม่แน่ใจ คุณสามารถลองคำนวณอาเรย์ของk -tuples ทั้งหมดด้วยรายการจากi: xและเรียงตามผลรวมของค่าสัมบูรณ์แล้วทำดัชนีลงในนั้น แนวคิดคืออาร์เรย์เหล่านี้เป็นส่วนนำหน้าของ "infinite array" หนึ่งตัวที่มีk -tuples ทั้งหมด
Zgarb

7

ภาษา Wolfram (Mathematica) , 61 ไบต์

SortBy[Range[-(x=2Abs@#+Boole[#>=0]),x]~Tuples~#2,#.#&][[x]]&

ลองออนไลน์!

(ใช้จำนวนเต็มจากนั้นความยาวของ tuple เป็นอินพุต)

ผกผัน:

If[OddQ[#],#-1,-#]/2&@Tr@Position[SortBy[Range[-(x=Ceiling@Norm@#),x]~Tuples~Length@#,#.#&],#]&

ลองออนไลน์!

มันทำงานอย่างไร

แนวคิดตรงไปตรงมา: เราเปลี่ยนอินพุตจำนวนเต็มเป็นจำนวนเต็มบวก (โดยการแมป 0,1,2,3, ... เป็น 1,3,5,7, ... และ -1, -2, -3, ... ถึง 2,4,6, ... ) จากนั้นจัดทำดัชนีลงในk -tuples ทั้งหมดเรียงตามระยะทางจากจุดเริ่มต้นและตามด้วยการผูกไทม์ของ Mathematica

แต่เราไม่สามารถใช้รายการที่ไม่มีที่สิ้นสุดดังนั้นเมื่อเรามองหาn th k -tuple เราจะสร้างk -tuples ของจำนวนเต็มในช่วง {- n , ... , n } นี้รับประกันได้ว่าจะพอเพราะn THเล็กที่สุดk -tuple บรรทัดฐานมีบรรทัดฐานน้อยกว่าnและ tuples ทั้งหมดของบรรทัดฐานnหรือน้อยกว่าที่จะถูกรวมอยู่ในรายการนี้

สำหรับสิ่งที่ตรงกันข้ามเราก็สร้างรายชื่อยาวเพียงพอของk -tuples ค้นหาตำแหน่งของที่กำหนดk -tuple ในรายการที่แล้วคว่ำ "การพับเป็นจำนวนเต็มบวก" การดำเนินการ


2
ทำงานด้วยอินพุต[15, 5]ทำให้พีซีของฉันพัง ...
JungHwan Min

2
มันจะเกิดขึ้น โดยหลักการแล้วอัลกอริธึมทำงานได้ทุกอย่าง แต่ในกรณีของคุณมันทำงานโดยการสร้าง 5 tuples ทั้งหมดจากช่วง {-31, .. , 31} แล้วเลือกอันดับที่ 31 ดังนั้นจึงค่อนข้างใช้หน่วยความจำมาก
Misha Lavrov

3

J, 7 ไบต์

#.,|:#:

รหัส J ในการทำสิ่งนี้เป็นเรื่องง่าย

ฟังก์ชั่นการจับคู่ที่ง่ายมาก (หรือฟังก์ชั่น tupling) คือการแทรกตัวเลขของการขยายฐานสองของตัวเลขแต่ละตัว ตัวอย่างเช่น(47, 79)จะจับคู่เป็นเช่นนี้:

1_0_0_1_1_1_1
 1_0_1_1_1_1
-------------
1100011111111

หรือ 6399 เห็นได้ชัดว่าเราสามารถพูดคุยทั่วไปกับ n-tuple ใด ๆ

ลองมาดูกันว่าคำกริยานี้ทำงานอย่างไรโดยใช้กริยา

#:เป็น anti-base สองเมื่อใช้แบบ monadically จะคืนค่าการขยายฐานสองของตัวเลข #: 47 79ให้ผลลัพธ์:

0 1 0 1 1 1 1
1 0 0 1 1 1 1

|:เป็นผู้ดำเนินการขนย้ายซึ่งเพียงแค่หมุนอาร์เรย์ การหมุนผลลัพธ์ของการ#: 47 79ให้:

0 1
1 0
0 0
1 1
1 1
1 1
1 1

เมื่อใช้แบบ monadically ,เป็นตัวดำเนินการ ravel มันจะสร้างรายการแบบ 1 มิติจากตาราง:

0 1 1 0 0 0 1 1 1 1 1 1 1 1

สุดท้ายแปลงกลับมาขยายตัวไบนารีให้เราผล#.6339

วิธีนี้จะใช้ได้กับสตริงจำนวนเต็มใด ๆ


7
มันทำงานอย่างไรกับจำนวนลบ?
Neil

2

Perl 6 , 148 bytes

my@s=map ->\n{|grep {n==abs any |$_},(-n..n X -n..n)},^Inf;my&f={$_==1??+*!!do {my&g=f $_-1;my@v=map {.[0],|g .[1]},@s;->\n{@v[n>=0??2*n!!-1-2*n]}}}

ลองออนไลน์!

Ungolfed:

sub rect($n) {
    grep ->[$x,$y] { abs($x|$y) == $n }, (-$n..$n X -$n..$n);
}

my @spiral = map { |rect($_) }, ^Inf;

sub f($k) {
    if ($k == 1) {
        -> $_ { $_ }
    } else {
        my &g = f($k-1);
        my @v = map -> [$x, $y] { $x, |g($y) }, @spiral;
        -> $_ { $_ >= 0 ?? @v[2*$_] !! @v[-1-2*$_] }
    }
}

คำอธิบาย:

  • rect($n)เป็นฟังก์ชั่นตัวช่วยที่สร้างพิกัดของจุดอินทิกรัลบนขอบของสี่เหลี่ยมจากพิกัด(-$n,$n)ถึง($n, $n)ที่จะ

  • @spiral เป็นรายการที่ไม่สิ้นสุดของจุดอินทิกรัลแบบขี้เกียจบนขอบสี่เหลี่ยมที่มีขนาดเพิ่มขึ้นโดยเริ่มจาก 0

  • f($k)ส่งคืนฟังก์ชันซึ่งเป็นการ$kอ้างถึงจากจำนวนเต็มถึง-tuples ของจำนวนเต็ม

ถ้า$kเป็น1, ผลตอบแทนการทำแผนที่เอกลักษณ์f-> $_ { $_ }

มิฉะนั้น&gเป็นการทำแผนที่ที่ได้รับซ้ำจากจำนวนเต็มถึง$k-1-tuples ของจำนวนเต็ม

จากนั้นเรา@spiralออกจากจุดกำเนิดและแต่ละจุดเป็น a- $ktuple โดยการใช้พิกัด X และผลลัพธ์ที่แบนราบของการโทรgด้วยพิกัด Y @vแมปนี้สร้างขึ้นอย่างเฉื่อยชาจะถูกเก็บไว้ในอาร์เรย์

@vมี$k-tuples ทั้งหมดที่เริ่มต้นด้วยดัชนี 0 ดังนั้นเมื่อต้องการขยายการจัดทำดัชนีไปยังจำนวนเต็มลบเราเพียงแมปอินพุตบวกกับตัวเลขคู่และอินพุตลบเป็นตัวเลขคี่ ฟังก์ชั่น (ปิด) จะถูกส่งกลับซึ่งค้นหาองค์ประกอบของ@vด้วยวิธีนี้


2

จาวาสคริปต์, 155 ไบต์

f=k=>x=>(t=x<0?1+2*~x:2*x,h=y=>(g=(v,p=[])=>1/p[k-1]?v||t--?0:p.map(v=>v&1?~(v/2):v/2):[...Array(1+v)].map((_,i)=>g(v-i,[...p,i])).find(u=>u))(y)||h(y+1))(0)

ระบุเวอร์ชันล่วงหน้า:

k => x => {
  // Map input to non-negative integer
  if (x > 0) t = 2 * x; else t = 2 * -x - 1;
  // we try to generate all triples with sum of v
  g = (v, p = []) => {
    if (p.length === k) {
      if (v) return null;
      if (t--) return null;
      // if this is the t-th one we generate then we got it
      return p;
    }
    for (var i = 0; i <= v; i++) {
      var r = g(v-i, [...p, i]);
      if (r) return r;
    }
  }
  // try sum from 0 to infinity
  h = x => g(x) || h(x + 1);
  // map tuple of non-negative integers back
  return h(0).map(v => {
    if (v % 2) return -(v + 1) / 2
    else return v / 2;
  });
}
  • ก่อนอื่นเราจับคู่จำนวนเต็มทั้งหมดกับจำนวนเต็มไม่ลบ:
    • ถ้า n> 0 ดังนั้น result = n * 2
    • มิฉะนั้นผลลัพธ์ = -n * 2 - 1
  • ประการที่สองเราให้ลำดับทั้งหมดกับ tuples จำนวนเต็มไม่ใช่ความยาว k ลบ:
    • คำนวณผลรวมขององค์ประกอบทั้งหมดส่วนที่เล็กกว่ามาก่อน
    • ถ้าผลรวมเท่ากันให้เปรียบเทียบจากซ้ายไปขวาอันที่เล็กกว่ามาก่อน
    • เป็นผลให้เราได้แผนที่สำหรับจำนวนเต็มที่ไม่ใช่ลบทั้งหมดไป tuples ด้วยจำนวนเต็ม k ไม่ใช่ลบ
  • ในที่สุดแผนที่จำนวนเต็มที่ไม่เป็นลบใน tuple ที่กำหนดในขั้นตอนที่สองกับจำนวนเต็มทั้งหมดที่มีสูตรที่คล้ายกันในขั้นตอนแรก

ฉันคิดว่าx<0?~x-x:x+xประหยัดได้ 2 ไบต์
Neil

2

ภาษา Wolfram (Mathematica) , 107 ไบต์

(-1)^#⌈#/2⌉&@Nest[{w=⌊(√(8#+1)-1)/2⌋;x=#-w(w+1)/2,w-x}~Join~{##2}&@@#&,{2Abs@#-Boole[#<0]},#2-1]&

ลองออนไลน์!

ผกผัน, 60 ไบต์

(-1)^#⌈#/2⌉&@Fold[+##(1+##)/2+#&,2Abs@#-Boole[#<0]&/@#]&

ลองออนไลน์!

คำอธิบาย:

Z -> N0 ผ่าน f(n) = 2n if n>=0 and -2n-1 if n<0

N0 -> N0 ^ 2 ผ่านทางตรงกันข้ามของฟังก์ชั่นการจับคู่

N0 -> N0 ^ k นำไปใช้ซ้ำกับหมายเลขด้านซ้ายซ้ำ ๆ จนกว่าเราจะได้ความยาว k

N0 ^ k -> Z ^ k ผ่าน f(n) = (-1)^n * ceil(n/2)องค์ประกอบที่ฉลาด


Mathematica, 101 ไบต์

(-1)^#⌈#/2⌉&@Nest[{a=#~IntegerExponent~2+1,#/2^a+1/2}~Join~{##2}&@@#&,{2Abs@#+Boole[#<=0]},#2-1]&

คล้ายกับด้านบน (ใช้ N แทน N0) แต่ใช้ส่วนกลับของ bijection f: N ^ 2 -> N ผ่าน f(a, b) = 2^(a - 1)(2b - 1)


คุณหมายถึง ... ไม่มี Mathematica ในตัวสำหรับสิ่งนั้น (เมื่ออลิซมี) ฉันพูดไม่ออก
JayCe

1

JavaScript, 112 ไบต์

k=>x=>(r=Array(k).fill(''),[...`${x<0?2*~x+1:2*x}`].map((c,i,s)=>r[(s.length-i)%k]+=c),r.map(v=>v&1?~(v/2):v/2))
  1. แปลงเป็นไม่ใช่เชิงลบ
  2. (n * k + i) ตัวเลข th ถึงหมายเลข i-th
  3. แปลงกลับ

@HermanLauenstein ไม่จำเป็นต้องย้อนกลับ?
tsh

ฉันคิดว่าx<0?~x-x:x+xประหยัดได้ 2 ไบต์
Neil

ใช้ -5 ไบต์[...BT${x<0?~x-x:x+x}BT].reverse().map((c,i)=>r[i%k]+=c),(เครดิตถึง @Neil สำหรับx<0?~x-x:x+x) .reverse()ถูกใช้แทน(s.length-i)เนื่องจากจะหลีกเลี่ยงความต้องการของพารามิเตอร์พิเศษsที่.mapหนึ่ง ไม่จำเป็นต้องย้อนกลับเนื่องจากไม่มีการใช้อาร์เรย์ชั่วคราวอีกครั้ง (ฉันยังไม่ได้ทดสอบ แต่น่าจะใช้งานได้)
Herman L

สามารถบันทึกไบต์อื่นได้ด้วยการแทนที่.fill('')ด้วย.fill(0)เนื่องจากศูนย์นำหน้าไม่สร้างความแตกต่าง (อย่างน้อยไม่เมื่อทดสอบใน Safari)
Herman L

@HermanLauenstein คุณลอง.fill`` หรือยัง อาจบันทึกอีกสองสามไบต์
Neil


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