B U ฉันลิตรแดนอีที


30

ความท้าทายนั้นง่ายมาก: เขียนโปรแกรมหรือฟังก์ชั่นที่เมื่อได้รับจำนวนเต็มไม่เป็นลบ จำกัด จะส่งออกอาร์เรย์ที่ซ้อนกัน

กฎระเบียบ

  • รหัสของคุณจะต้องผลิตที่ไม่ซ้ำกันอาร์เรย์ที่ซ้อนกันที่ถูกต้องสำหรับทุกจำนวนเต็ม 0 ≤ n <2 วันที่ 31
  • ทุกอาร์เรย์ที่ซ้อนกันเป็นไปได้ที่มีถึง 16 วงเล็บเปิดจะต้องออกมาในช่วงนี้ (นี่ไม่ได้หมายความว่ารหัสของคุณจะไม่สามารถส่งออกอาร์เรย์ที่ซ้อนกันที่มีวงเล็บเปิดมากกว่า 16 ตัว)
  • รหัสของคุณอาจแสดงการแทนค่าสตริงของอาร์เรย์ที่ซ้อนกันแทนที่จะเป็นอาร์เรย์จริง (โดยมีหรือไม่มีเครื่องหมายจุลภาค)

การแมปหนึ่งที่เป็นไปได้:

0 -> []
1 -> [[]]
2 -> [[[]]]
3 -> [[], []]
4 -> [[[[]]]]
5 -> [[[], []]]
6 -> [[[]], []]
7 -> [[], [[]]]
8 -> [[], [], []]
9 -> [[[[[]]]]]
etc.

เกณฑ์การให้คะแนน

นี่คือดังนั้นโค้ดที่สั้นที่สุดในหน่วยไบต์ชนะ


มีข้อ จำกัด ด้านเวลา / หน่วยความจำหรือไม่?
เดนนิส

@Dennis 1 ชั่วโมงดูเหมือนว่าจะมีข้อ จำกัด ด้านเวลาหรือไม่? ฉันไม่มีเงื่อนงำอะไรที่สมเหตุสมผลสำหรับความจำ
ETHproductions

หน่วยความจำไม่ใช่เรื่องใหญ่หากมีเวลา จำกัด หนึ่งชั่วโมงดูเหมือนว่าใจกว้างมาก ฉันไม่ต้องการรอหนึ่งชั่วโมงเต็มเพื่อตรวจสอบว่ารหัสของฉันเร็วพอหรือไม่
เดนนิส

4
ฉันไม่ต้องการเวลา จำกัด ที่ให้ขอบเขตเพิ่มเติมสำหรับความคิดริเริ่ม
Ton Hospel

2
@TonHospel คุณสามารถส่งออกโดยไม่มีเครื่องหมายจุลภาค ฉันเดาว่าจะไม่มีการ จำกัด เวลาหากคุณสามารถพิสูจน์ได้ว่ารายการของคุณถูกต้อง
ETHproductions

คำตอบ:


12

Python 2.7, 172 149 124 118 ไบต์

x=input();y="";z=0
for b in bin(x)[2+(x<1):]:y+="[]"[b<"1"];z+=b>"0"or-1;z+=99*(z<0)
print"["+(y,"[]"*(x+16))[z>0]+"]"

คำอธิบาย:

กำหนด bijection โดย[1และ↔] 0การจัดเรียงของวงเล็บใด ๆ ที่สามารถเขียนเป็นเลขฐานสองและในทางกลับกันเช่น[][]1010(10) และ[[][]]110100(52) ทั้งหมดเตรียมการที่ถูกต้องถึง 15 วงเล็บเปิด (30 วงเล็บทั้งหมด) ถูกปกคลุมไปด้วยตัวเลขที่มีถึง 30 บิต (ละเว้นศูนย์ชั้นนำ) ซึ่งเป็นตัวเลขที่แม่นยำน้อยกว่า 2 วันที่ 31

for-loop แรกให้ค่าผกผันของการให้ค่านี้แปลงตัวเลขเป็นการจัดเรียงของวงเล็บในขณะที่ตรวจสอบว่าการจัดเรียงนั้นถูกต้อง

การจัดเรียงที่ไม่ถูกต้องจะถูกแทนที่ภายในคำสั่งการพิมพ์ด้วยวงเล็บยาวเพื่อหลีกเลี่ยงการชน ตัวอย่างเช่น11(3) ↔ [[ไม่ถูกต้องดังนั้นเราจึงเชื่อมวงเล็บ 3 + 16 แทน สิ่งนี้ทำให้มั่นใจได้ว่าการเตรียมการทั้งหมดนั้นไม่เหมือนใคร

ผลการจัดวางอยู่ภายในคู่ของวงเล็บเพื่อให้อาร์เรย์ที่ซ้อนกันเพื่อที่ว่า1010(10) กลายเป็น[[][]]และ110100(52) [[[][]]]กลายเป็น วงเล็บเปิดพิเศษหมายความว่าตอนนี้เราได้ครอบคลุมอาร์เรย์ทั้งหมดด้วยวงเล็บเปิด 16 อัน


โปรแกรมต่อไปนี้สามารถใช้เพื่อหาตัวเลขสำหรับอาร์เรย์ที่กำหนดซึ่งมีวงเล็บมากถึง 16 ตัว

s=raw_input();o="";
for c in s[1:-1]:
 if c=="[":o+="1"
 if c=="]":o+="0"
print int(o,2)

การใช้ความตั้งใจอย่างไม่เหมาะสมเมื่อเขาระบุ "ไม่เหมือนใคร"
Ton Hospel เมื่อ

นั่นเป็นเพียงอัจฉริยะ ทำได้ดี. (และอนุญาตให้ใช้รูปแบบที่ไม่มีเครื่องหมายจุลภาค)
ETHproductions

12

Python ขนาด153 128 ไบต์

s=l=0;r="";n=input()
for d in bin(n)[2:]*(n>0):c=d<"1";l=[l,s>1][c];r+="]"*c+(1-l*c)*"[";s+=1-c-l*c
print"["+r+"["*l+"]"*(s+l+1)

เราจับคู่หมายเลขnกับรายการที่ซ้อนอยู่โดยดูจากเลขฐานสองจากซ้ายไปขวา อัลกอริทึมงานนี้สำหรับจำนวนใด ๆ ที่ไม่เพียงภายใต้ 2 32

  1. ถ้าเลขฐานสองในปัจจุบันเป็นที่ 1, [เอาท์พุท
  2. ][มิฉะนั้นถ้าลำดับของวงเล็บที่เราส่งออกได้เพื่อให้ห่างไกลจะได้รับจากวงเล็บปิดเดียวเอาท์พุท
  3. มิฉะนั้นถ้านี้เป็นวันสุดท้ายใน 0 ][เลขฐานสองเอาท์พุท
  4. ]ส่งออกมิฉะนั้น

ในที่สุดเราปิดวงเล็บที่เปิดอยู่


5

ช้อน 63 ไบต์ (501 บิต)

000001001001001011001101001010011011111001010001000000101010
101101100110100101101001000101100010001000000100011000010000
000000000000001110111110010000001110110110010100100100100100
000110011010001000000110110000010000001010110011011011011001
000000011010010010010001000000111011011011101001001001000110
110110010100100101011001000100000011010001000000111011011001
010010010010010001101101101001000110110010110001101101101101
100100010001010010001010011011001000000011001101001001010010
000001100101001000111

นี่คือโปรแกรม brainfuck ต่อไปนี้ที่แปลงเป็นช้อน:

-[+[+<]>>+]<+++.[->+>+<<]>>++>>,[>-[<->-----]+<+++[-<+<<.>>>>-<]>[-<<-[->+<]<<<[-]>>>>[-<+<<<+>>>>]<<.>>+<[>-]>[-<+<<.>>>>]<<>>]<,]<<<<[>.>.<<[-]]>>>+[-<.>]+

อ่านจำนวนเต็มเป็นเลขฐานสองบน stdin และส่งออกรายการซ้อนบน stdin ต้องป้อน 0 เพื่อเป็นสตริงว่าง (ไม่มีตัวเลข) และต้องการล่ามสมองที่มีเซลล์ 8 บิต อัลกอริทึมเช่นเดียวกับคำตอบของฉันหลาม

รุ่นที่อ่านได้:

-[+[+<]>>+]<+++.           push open bracket and print it
[->+>+<<]                  dup
>>++                       increment to close bracket

>>,[                       read input loop
    >-[<->-----]+<+++          subtract 48 and set up if/else
    [-                         if c == 1
        <+                         increment s
        <<.>>>                     output open bracket
    >-<]>[-<                   else
        <-[->+<]                   decrement and move s
        <<<[-]                     zero l
        >>>>[-<+<<<+>>>>]          l = s and restore s
        <<.>                       output close bracket
        >+<[>-]>[-                 if s == 0
            <+                         undo s decrement
            <<.                        output open bracket
        >>>>]<<
    >>]<
,]

<<<<[                      if l
    >.>.                   output pair
<<[-]]
>>>+[-<.>]                 output close bracket s+1 times

3
เมื่อไม่นานมานี้เราได้มีการพูดคุยกันเกี่ยวกับคำตอบอื่นและดูเหมือนว่าจะไม่มีผู้แปลจริงที่สามารถจัดการไฟล์ 63- ไบต์ การใช้การอ้างอิงใช้ไบต์ 0x30 และ 0x31 ดังนั้นคำตอบนี้จะต้องใช้ไฟล์501 ไบต์
เดนนิส


5

Perl, 80 79 ไบต์

ใช้อัลกอริทึมของorlpอีกครั้งแต่ครั้งนี้ฉันตรวจสอบครั้งแรกหากใช้งานได้ ...

รวม +1 สำหรับ -p

ให้หมายเลขอินพุตใน STDIN

nest.pl <<< 8

nest.pl:

#!/usr/bin/perl -p
($_=sprintf"%b",$_).=2x(s^.^$&or++$n-pos&&/.0/g?++$n%1:$`&&21^eg-$n);y;102;();

โซลูชันของLinusคือ 64 ไบต์ใน perl:

#!/usr/bin/perl -p
$_=sprintf"%b",/.+/g;$_=10x($&&&$&+16)if!/^(1(?1)*0)+$/;y;10;()

วิธีการแก้ปัญหาของDennisคือ 59 ไบต์ใน perl (ยิ่งช้าลงสำหรับคนจำนวนมาก):

#!/usr/bin/perl -p
1while$_-=(sprintf"%b",$n++)=~/^(1(?1)*0)+$/;$_=$&;y;10;()

ฉันรู้สึกว่าคุณควรให้คะแนนนี้เป็น 65 ไบต์ (ไม่ใช่ 64 จริง ๆ )
ไลนัส

1
@Linus แม้ว่ากฎของคุณจะยอดเยี่ยมและสมควรได้รับ upvotes ทั้งหมด แต่ฉันคิดว่ามันโกงไปหน่อย สำหรับการให้คะแนน-pจะถูกนับเป็น 1 ไบต์พิเศษ
Ton Hospel

5

Python 3, 120 114 bytes

def f(n,k=0):
 while~n:
  k+=1
  try:r=eval(bin(k).translate({48:'],',49:'['})[3:-1])+[];n-=1
  except:0
 print(r)

ทดสอบบนIdeone

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

ฟังก์ชั่นที่กำหนดไว้จะเข้าnและเริ่มต้นkไป0 เราจะเพิ่มค่าkจนกระทั่งn + 1ค่าของkทำให้ได้ผลลัพธ์ที่ถูกต้อง ทุกครั้งที่เราพบค่าk , nจะลดลงเมื่อถึง-1 , ~nให้ผลเป็น0 , และรายการrที่สอดคล้องกับค่าสุดท้ายของkจะถูกพิมพ์

การแมปบางส่วนจากจำนวนเต็มบวกไปยังรายการซ้อน (เช่นk ↦ r ) จะต้องมีความหลากหลายทางชีวภาพ แต่ไม่มีข้อ จำกัด อื่น ๆ คำตอบที่ใช้ในคำตอบนี้ทำงานดังนี้

  1. แปลงkเพื่อเป็นตัวแทนสตริงไบนารีจ้องมองด้วย0B

    ยกตัวอย่างเช่น44 ↦ "0b101100"

  2. แทนที่ทั้งหมด0 's (รหัสจุด48 ) ในการเป็นตัวแทนสตริงกับสตริง']'และทุก1 ' s (จุดรหัส49 ) กับ[

    ยกตัวอย่างเช่น"0b101100" ↦ "], B [], [[]]"

  3. ลบอักขระสามตัวแรก (ตรงกับ"0b" ) และอักขระต่อท้าย (หวังว่าจะเป็นเครื่องหมายจุลภาค)

    ยกตัวอย่างเช่น"], B [], [[]]" ↦ "[], [[]]"

  4. ลองประเมินรหัสที่สร้างขึ้น หากผลลัพธ์นี้มีข้อผิดพลาดkจะไม่ถูกแมปกับรายการใด ๆ

    ยกตัวอย่างเช่น"[], [[]]" ↦ ([], [[]])

  5. เชื่อมผลลัพธ์ (ถ้ามี) เข้ากับรายการที่ว่าง หากผลลัพธ์นี้มีข้อผิดพลาดkจะไม่ถูกแมปกับรายการใด ๆ

    ตัวอย่างเช่น([], [[]]) + []ข้อผิดพลาดเนื่องจาก+ไม่สามารถเชื่อมต่อรายการและสิ่งอันดับ


4

Haskell, 71 ไบต์

p 1=["[]"]
p n=['[':h++t|k<-[1..n-1],h<-p k,_:t<-p$n-k]
((p=<<[1..])!!)

ฟังก์ชั่นหลักในดัชนีบรรทัดสุดท้ายลงในรายการของอาร์เรย์ที่ซ้อนกันทั้งหมดเรียงตามขนาด (จำนวนวงเล็บเปิด) ดังนั้นอาร์เรย์ที่มีขนาดสูงสุด 16 รายการทั้งหมดจะถูกระบุไว้ก่อน

ก่อนอื่นมาดูโค้ดที่ดีกว่าและสั้นกว่ากัน แต่ตัวพิมพ์ดีดของ Haskell ปฏิเสธที่จะยอมรับ

p 1=[[]]
p n=[h:t|k<-[1..n-1],h<-p k,t<-p$n-k]
((p=<<[1..])!!)

ฟังก์ชั่นpในการป้อนข้อมูลnให้รายการของขนาดอาร์เรย์ที่ซ้อนกันทั้งหมดn(วงเล็บเปิด) สิ่งนี้ทำซ้ำ แต่ละแถวดังกล่าวประกอบด้วยหัวh(สมาชิกรายแรก) ที่มีขนาดkและบางส่วนt(สมาชิกคนอื่น ๆ ) ที่มีขนาดn-kทั้งสองขนาดที่ไม่ใช่ศูนย์ n==1หรือมันเป็นอาร์เรย์ที่ว่างเปล่าขนาด

นิพจน์p=<<[1..]นั้นจะแบนp(1), p(2), ...เป็นรายการอนันต์เดียวของอาร์เรย์ทั้งหมดที่เรียงลำดับตามขนาด

[ [], [[]], [[],[]], [[[]]], [[],[],[]], [[],[[]]], [[[]],[]], [[[],[]]], ...

และดัชนีฟังก์ชั่นหลักเข้ามา

... หรือถ้าหาก Haskell ไม่ได้คร่ำครวญเกี่ยวกับ "สร้าง [ing] ประเภทอนันต์: t ~ [t]" Haskell ไม่สามารถแสดงรายการอนันต์ด้านบนซึ่งองค์ประกอบต่าง ๆ เป็นอาร์เรย์ที่ซ้อนกันโดยพลการ องค์ประกอบทั้งหมดจะต้องมีประเภทเดียวกัน แต่ประเภท t ไม่สามารถเหมือนกับรายการของ t ในความเป็นจริงฟังก์ชั่นpไม่สามารถกำหนดประเภทที่สอดคล้องกันโดยไม่ต้องพิมพ์ขึ้นอยู่กับซึ่ง Haskell ขาด

ดังนั้นเราจึงทำงานกับสตริงของวงเล็บจำลองการทำงานของ cons โดยทำหน้าที่[และ]ตัวละคร ใช้เวลาเพิ่มอีก 9 ไบต์ อันตรายของการเล่นกอล์ฟในภาษาที่ปลอดภัย


3

Haskell, 87 82 ไบต์

0#0=[""]
n#m=['[':x|n>0,x<-(n-1)#m]++[']':x|n<m,x<-n#(m-1)]
(([0..]>>= \y->y#y)!!)

ส่งออกองค์ประกอบอาร์เรย์ ตัวอย่างการใช้งาน: ->(([0..]>>= \y->y#y)!!) 3"[][]"

ฟังก์ชัน#สร้างอาร์เรย์ที่ซ้อนกันทั้งหมดเป็นสตริงสำหรับวงเล็บnเปิดและmปิดโดยการติดตามจำนวนแต่ละอันที่เหลือ เริ่มต้นด้วยn == mเสมอ ฟังก์ชั่นหลักเรียกร้องy # yให้ทุกคนy <- [0,1,...]และเลือกองค์ประกอบที่ดัชนีที่กำหนดโดยการป้อนข้อมูล


2

MATL , 31 ไบต์

O`@BEqXJYs0&)0>w~hA+tG>~]x92J-c

ลองออนไลน์! หรือตรวจสอบกรณีทดสอบสองสามกรณีแรก (ใช้เวลาสองสามวินาที)

แผนที่ที่ผลิตคือ:

0 -> []
1 -> [[]]
2 -> [[][]]
3 -> [[[]]]
4 -> [[][][]]
5 -> [[][[]]]
6 -> [[[]][]]
7 -> [[[][]]]
...

คำอธิบาย

รหัสพร้อมทดสอบการเพิ่มเลขฐานสองกับหลัก0แทนที่ด้วย-1; นั่นคือการใช้1และ-1เป็นตัวเลข ตัวเลข1จะเป็นตัวแทน'['และ-1จะเป็นตัวแทน']'ของ

นับจนถึงโปรแกรมn +1 ถูกต้องตัวเลขที่ได้รับ ตัวเลขถูกต้องหากมีสองเงื่อนไขต่อไปนี้:

  1. ผลรวมของหลักคือศูนย์ (นั่นคือมีจำนวนเท่ากัน1และ-1)
  2. ผลรวมสะสมของตัวเลขนั้นเป็นค่าบวกเสมอ (นั่นคือจำนวน1หลักของสะสมจะมากกว่าจำนวนเสมอ-1) ยกเว้นในตอนท้าย (ที่เป็นศูนย์ตามเงื่อนไข 1)

เมื่อได้รับตัวเลขที่ถูกต้องn +1 แล้วหมายเลขสุดท้ายจะถูกถอดเสียงโดยการเปลี่ยน1เป็นเข้า[และ-1ออก]จากนั้นจะปรากฏขึ้น

รหัส:

O          % Push 0: initial count of valid numbers
`          % Do...while
  @        %   Push iteretation index k, starting at 1
  B        %   Convert to binary. For example, k=6 gives [1 1 0 0]
  Eq       %   Multiply by 2, subtract 1: transforms [1 1 0 0] into [1 1 -1 -1]
  XJ       %   Copy that to clipboard J, without popping it
  Ys       %   Cumulative sum: gives [1 2 1 0]
  0&)      %   Split array into its final element and the rest. Gives 0, [1 2 1]
  0>       %   Yields 1 for positive entries (condition 2). So in this case it
           %   gives [1 1 1]
  w        %   Swap: moves second-top element in the stack (0 in this case) to top
  ~        %   Negate: yields 1 if input is 0 (condition 1). Gives 1 in this case
  h        %   Concatenate horizontally. Gives [1 1 1 1]
  A        %   All: gives 1 if all elements are 1. Gives 1 in this case, meaning
           %   that this k is valid
  +        %   Add the result (0 or 1) to the count of valid numbers
  t        %   Duplicate
  G        %   Push input n
  >~       %   Loop condition: false (exit loop) if count exceeds input n
]          % End loop. At this point the result is in clipboard J, in 1/-1 format
x          % Delete count
92         % Push 92. Will be used to convert 1, -1 to '[', ']' (ASCII 91, 93)
J          % Push result in 1/-1 format
-          % Subtract: converts 1 to 91, -1 to 93
c          % Convert to char. Implicitly display
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.