ชัดเจนวงเล็บรถไฟ APL


19

ใน APL คุณสามารถเขียนฟังก์ชั่นโดยปริยายเรียกว่ารถไฟ พวกเขาทำงานอย่างไรไม่เกี่ยวข้องกับความท้าทายนี้ นี่คือวิธีที่แตกต่างกันที่พวกเขาสามารถจัดกลุ่มโดยใช้เป็นฟังก์ชั่น:

⍴      -> ⍴
⍴⍴     -> ⍴⍴
⍴⍴⍴    -> ⍴⍴⍴
⍴⍴⍴⍴   -> ⍴(⍴⍴⍴)
⍴⍴⍴⍴⍴  -> ⍴⍴(⍴⍴⍴)
⍴⍴⍴⍴⍴⍴ -> ⍴(⍴⍴(⍴⍴⍴))
...

คำสั่งซื้อยังคงเหมือนเดิม ขั้นตอนคือตราบใดที่มีมากกว่า 3 ฟังก์ชั่นอย่างเข้มงวดฟังก์ชั่น 3 ครั้งสุดท้ายจะถูกจัดกลุ่มเป็นหนึ่งฟังก์ชั่น หากเราพบรถไฟซ้อนกันเราจะวงเล็บเป็นอันดับแรกก่อนดำเนินการต่อ นี่คือขั้นตอนที่ใช้กับ⍴⍴⍴⍴⍴⍴:

Step 0: ⍴⍴⍴⍴⍴⍴
There are strictly more than 3 functions, repeat.
Step 1: ⍴⍴⍴(⍴⍴⍴)
There are strictly more than 3 functions, repeat.
Step 2: ⍴(⍴⍴(⍴⍴⍴))
There are 3 or less functions, we're done.

นี่เป็นขั้นตอนเดียวกันกับ⍴⍴⍴(⍴⍴)⍴(⍴⍴⍴⍴(⍴⍴⍴))⍴⍴:

Step 0: ⍴⍴⍴(⍴⍴)⍴(⍴⍴⍴⍴(⍴⍴⍴))⍴⍴
There are strictly more than 3 functions, repeat.
We have met a nested train, applying procedure to that first:
  Step 0: ⍴⍴⍴⍴(⍴⍴⍴)
  There are strictly more than 3 functions, repeat.
  We have met a nested train, applying procedure to that first:
    Step 0: ⍴⍴⍴
    There are 3 or less functions, we're done.
  Step 1: ⍴⍴(⍴⍴(⍴⍴⍴))
  There are 3 or less functions, we're done.
Step 1: ⍴⍴⍴(⍴⍴)⍴((⍴⍴(⍴⍴(⍴⍴⍴)))⍴⍴)
There are strictly more than 3 functions, repeat.
We have met a nested train, applying procedure to that first:
  Step 0: ⍴⍴
  There are 3 or less functions, we're done.
Step 2: ⍴⍴⍴((⍴⍴)⍴((⍴⍴(⍴⍴(⍴⍴⍴)))⍴⍴))
There are strictly more than 3 functions, repeat.
Step 3: ⍴(⍴⍴((⍴⍴)⍴((⍴⍴(⍴⍴(⍴⍴⍴)))⍴⍴)))
There are 3 functions or less, we're done.

อินพุต

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

เอาท์พุต

อีกครั้งคุณอาจเลือก 3 ตัวอักษรที่แตกต่างกัน 2 สำหรับวงเล็บและ 1 สำหรับฟังก์ชั่น โปรดทราบว่าพวกเขาไม่จำเป็นต้องเหมือนกันกับที่เลือกสำหรับการป้อนข้อมูล แต่พวกเขาจะต้องสอดคล้อง

กฎระเบียบ

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

กรณีทดสอบ

ตัวอักษรที่ใช้ที่นี่คือ()⍴คุณควรแทนที่ด้วยตัวอักษรที่คุณเลือก

⍴                          -> ⍴
⍴                          -> ⍴
⍴⍴                         -> ⍴⍴
⍴⍴⍴                        -> ⍴⍴⍴
⍴⍴⍴⍴                       -> ⍴(⍴⍴⍴)
⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴            -> ⍴⍴(⍴⍴(⍴⍴(⍴⍴(⍴⍴(⍴⍴(⍴⍴⍴))))))
⍴⍴⍴⍴⍴(⍴⍴⍴)⍴⍴(⍴(⍴⍴⍴)⍴⍴⍴)⍴⍴⍴ -> ⍴(⍴⍴(⍴⍴((⍴⍴⍴)⍴(⍴(⍴(⍴⍴⍴)(⍴⍴⍴))(⍴⍴⍴)))))
(⍴⍴⍴)(⍴⍴⍴)(⍴⍴⍴)            -> (⍴⍴⍴)(⍴⍴⍴)(⍴⍴⍴)
(⍴⍴⍴)(⍴⍴⍴)⍴⍴⍴              -> (⍴⍴⍴)(⍴⍴⍴)(⍴⍴⍴)
⍴⍴(⍴)⍴⍴                    -> ⍴⍴(⍴⍴⍴)
((⍴⍴))                     -> ⍴⍴
⍴⍴((⍴⍴))⍴⍴                 -> ⍴⍴((⍴⍴)⍴⍴)

ความท้าทายนี้ได้รับการโพสต์ใน Sandbox หากคุณมีสิทธิ์ที่จำเป็นคุณสามารถดูโพสต์จาก sandbox ที่นี่


2
ผมคิดว่าอย่างเต็มที่เป็นชื่อที่ดีกว่าอย่างเห็นได้ชัด
อดัม


@ Adámฉันคาดหวังว่าคำตอบอ้างอิงนั้นจะไม่ได้รับ upvotes มาก;)
Erik the Outgolfer

@ Adám ส่วนที่ชัดเจนในชื่อหมายถึงความจริงที่ว่าคุณจะต้องลบวงเล็บที่ไม่จำเป็น สิ่งที่คุณควรทำอย่างเต็มที่เมื่อคุณตอบคำถาม: p
Erik the Outgolfer

เป็นความจริงไหมว่าฟังก์ชั่นนี้จะเป็น idempotent เสมอ?
แยกผลไม้

คำตอบ:


7

APL (Dyalog Classic) , 71 68 65 63 ไบต์

0{⍵≡⍕⍵:⍵⋄⍬≡⍵:'⍬'1=≢⍵:⍺∇⊃⍵⋄3≥≢⍵:⍺⌽')(',⍣⍺∊1∇¨⍵⋄⍺∇¯3(↓,∘⊂1∇↑)⍵}⍎

ลองออนไลน์!

ตัวละครที่ฉันเลือกสำหรับ I / O มี'(', และ')''⍬'

วิธีนี้เป็นรถไฟ APL

แยกวิเคราะห์อินพุตราวกับว่ามันเป็นอาร์เรย์ซ้อนกัน - ต้นไม้ที่มีเวกเตอร์ตัวเลขว่างเปล่า ( ) เหมือนใบไม้

dfn (เช่นแลมบ์ดา - { }) สำรวจต้นไม้แบบวนซ้ำและแปลงเป็นสตริงที่ถูกต้อง อาร์กิวเมนต์ซ้ายจะควบคุมว่าควรเพิ่มวงเล็บในระดับปัจจุบันหรือไม่หากจำเป็น

dfn จัดการกรณีต่อไปนี้ตามอาร์กิวเมนต์ที่ถูกต้อง:

  • หากเป็นสตริง ( ⍵≡⍕⍵) ให้ส่งคืน

  • ถ้าเป็นเช่นนั้นกลับถ่าน'⍬'

  • หากเป็นซิงเกิลตันให้เจาะลึกลงไป ( เป็นสัญลักษณ์สำหรับการโทรซ้ำ)

  • หากความยาวของมันคือ≤3ให้ชดเชยสำหรับแต่ละรายการและล้อมรอบด้วย()หากจำเป็น

  • มิฉะนั้นให้เรียกเก็บเงินสำหรับ 3 หางอีกครั้งเติมทั้งหมดยกเว้น 3 หางและเรียกคืนอีกครั้ง


ดูเหมือนว่า 63 ตัวอักษรส่วนใหญ่เป็น Unicode การเข้ารหัสตัวอักษรอะไรที่ก่อให้เกิด 63 ไบต์สำหรับสิ่งนี้? ฉันทำ 141 ไบต์ใน UTF8
Corey

3
@Corey APL มี 8 บิตหน้ารหัสของตัวเอง
zwol

@Corey โพสต์เมตาที่เกี่ยวข้อง
อดัม

@ Adámขอบคุณสำหรับสิ่งนั้น ฉันดู แต่ไม่รู้ว่าจะค้นหาอะไรเพื่อให้ได้คำตอบนั้น
Corey

3

Python 2 , 224 208 204 ไบต์

-16 ไบต์ขอบคุณ Mr. Xcoder -4 ไบต์ขอบคุณ ovs

r=str.replace
p='p'
def c(l):
 while len(l)>3:l=l[:-3]+(l[-3:],)
 return l and map(c,l)or l
print r(r(r(r(r(`c(eval(r(r(r(input(),'(p)',p),p,'[],'),')','),')))`,'[]',p),*'[('),*'])'),' ',''),',','')[1:-1]

ลองออนไลน์! หรือลองกรณีทดสอบทั้งหมด

รหัสที่สามารถแบ่งออกเป็น 3 ขั้นตอนสำคัญ: แปลงการป้อนข้อมูลลงในรายการที่ซ้อนกันและแทนที่
(p)->pฟังก์ชั่นเดียวpจะถูกแทนที่ด้วยรายการที่ว่างเปล่า

eval(r(r(r(input(),'(p)',p),p,'[],'),')','),'))

ฟังก์ชันแบบเรียกซ้ำเพื่อใช้กฎ "3 หรือน้อยกว่า" ในรายการปัจจุบันและเรียกตัวเองในรายการย่อยทั้งหมด

def c(l):
 while len(l)>3:l=l[:-3]+(l[-3:],)
 return l and map(c,l)or l

มีการแทนที่จำนวนมากเพื่อจัดรูปแบบเป็นรูปแบบผลลัพธ์ที่ต้องการ

r(r(r(r(r(`c(...)`,'[]',p),*'[('),*'])'),' ',''),',','')[1:-1]


1
สิ่งนี้ไม่ลดความซับซ้อน((pp))(หรือp((pp))p)
Martin Ender

2

CJam , 56 ไบต์

เอาชนะ APL!

lW%~]]]{{_,{K_,({~}|}&}%{_,3>}{3/(aa\+:~}w}:K~~`1>W<W%S/

ลองออนไลน์!

ใช้งานได้ (ฉันคิดว่า) และฉันไม่รู้ว่าทำไม ...

อักขระอินพุตใช้][Tสำหรับ()⍴และอักขระเอาต์พุตใช้][0สำหรับ()⍴(ใช่หมายความว่าอักขระเหล่านั้นถูกย้อนกลับจากสิ่งที่คุณคาดหวังตัวอย่างเช่นคุณอาจส่งผ่านTTT]TT[T]TTTT]TTT[[TT)

ภาพรวมระดับสูง

โปรแกรมทำงานกับอินพุตย้อนกลับเพราะสะดวกกว่า ในการแยกวิเคราะห์อินพุตเราใช้ประโยชน์จาก parser ของ CJam - การย้อนกลับและดำเนินการอินพุตให้รูปแบบ (ย้อนหลัง) แยกวิเคราะห์ของอินพุต

Kจากนั้นเราจะกำหนดขั้นตอน Kทำงานส่วนใหญ่สำหรับการส่งผลงานของเราและทำงานดังนี้:

  • อาร์เรย์อินพุตจะเป็นการรวมกันของศูนย์และอาร์เรย์ย่อยที่ไม่มีข้อ จำกัด ระบุอาร์เรย์ย่อยและนำKไปใช้ซ้ำกับพวกเขา ผลลัพธ์ควรเป็นอีกอาร์เรย์หนึ่งและถ้าอาร์เรย์นี้ประกอบด้วยเพียงองค์ประกอบเดียวให้แกะมันออก (ซึ่งเป็นการกำจัดวงเล็บที่ซ้ำซ้อน)
  • ตราบใดที่ผลลัพธ์มีองค์ประกอบมากกว่าสามรายการให้จัดกลุ่มสามรายการแรก (ไม่ใช่สามรายการสุดท้ายโปรดจำไว้ว่ากำลังประมวลผลอินพุตด้านหลัง) เป็นรายการเดียว
  • ส่งคืนผลลัพธ์

โดยการนำKไปใช้กับการป้อนข้อมูลเราได้รับรูปแบบวงเล็บที่ถูกต้องของสิ่งที่ใส่ (สิ่งเดียวที่ควรทราบคือการที่เราห่อข้อมูลในรายการเดี่ยวและแกะมันในภายหลังเหตุผลสำหรับสิ่งนี้คือเราต้องการตัวอย่างที่ปลดเป้ เพื่อนำไปใช้กับโปรแกรมระดับบนสุดไม่ใช่เพียงแค่อาร์เรย์ย่อย) หลังจากนั้นเราเพิ่งนำการจัดรูปแบบขั้นต่ำไปใช้เพื่อให้ได้ผลลัพธ์ของเรา

คำอธิบายบางอย่างสำหรับบิต golfed

กอล์ฟที่ฉันภูมิใจที่สุดคือการใช้,การตรวจสอบระหว่างจำนวนเต็มและอาร์เรย์

  • ถ้าด้านบนของสแต็คเป็นจำนวนเต็มn , ,สร้างช่วง[0..n) เนื่องจากจำนวนเต็มเดียวที่เราจะพบคือ0นี่จะให้รายการเปล่ากับเราเสมอ[]ซึ่งเป็นเท็จ
  • หาก top-of-stack เป็นอาร์เรย์ให้,ใช้ความยาวของมัน เนื่องจากอาร์เรย์ทั้งหมดที่เราพบจะไม่ว่างนี่จะให้จำนวนเต็มบวกเสมอซึ่งก็คือความจริง

กอล์ฟอีกอันที่น่าสนใจคือวิธีที่ฉันใช้จัดกลุ่มองค์ประกอบสามประการแรกของอาร์เรย์ มันค่อนข้างคล้ายกับการส่งของฉัน "ทัวริงล่ามภาษาที่สมบูรณ์รหัสกอล์ฟ" CJam ไม่มีวิธีสั้น ๆ ในการแบ่งอาร์เรย์ออกเป็นสองส่วน (คุณสามารถลองตัดส่วนแรกแล้วส่วนอื่น ๆ ในขณะที่รักษาอาร์เรย์เดิมและดัชนีบนกองซ้อน แต่ไม่ได้ผลดีมาก) ดังนั้นสิ่งที่ฉันทำคือการใช้แทน3/ซึ่งกลุ่มอาร์เรย์ลงในบล็อกของ 3. จากนั้นผมก็สามารถปรากฏออกองค์ประกอบแรก(ห่อในอาร์เรย์สองครั้งแล้วผนวกกลับไปยังจุดเริ่มต้นของรายการaa \+เหตุผลที่เราห่อในอาร์เรย์สองครั้งคือเราต้องถอดเลเยอร์ด้วย:~เนื่องจากเราเพิ่งจัดกลุ่มส่วนที่เหลือของอาเรย์เป็นส่วนเช่นกัน


nitpick: นี้เต้น APL โดยไม่ต้อง builtins
Erik the Outgolfer

@EriktheOutgolfer ยุติธรรมเพียงพอ
แยกผลไม้

0

JavaScript (ES6), 149 146 ไบต์

i='a';f=s=>s==(s=s[R='replace'](/\((\w+)\)/,(q,t)=>(f[q=i+=0]=f(t),q)))&&s==(s=s[R](/(?!^)((a0+|p){3})$/,"($1)"))?s[R](/a0+/g,t=>`(${f[t]})`):f(s)
<textarea cols=80 id=I>ppp(pp)p(pppp(ppp))pp</textarea><br>
<button onclick=O.innerText=f(I.value)>Run</button><br>
<pre id=O></pre>

ใช้()pแม้ว่าคุณจะใช้ตัวอักษรที่แตกต่างกันคุณก็สามารถเปลี่ยนpส่วนท้ายได้

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