De-Parenthesizing สตริง


25

กำหนดสตริงที่วงเล็บให้ถูกต้องเป็นอินพุตเอาต์พุตรายการของสตริงย่อยที่ไม่ว่างทั้งหมดภายในวงเล็บที่ตรงกัน แต่ละสตริงย่อยควรเป็นลำดับของอักขระในวงเล็บที่ตรงกันตรงกันทุกประการ ควรระบุรายการซับสเตอรตามลําดับความลึกและแสดงซับสตริปที่มีความลึกเท่ากันตามลําดับที่เกิดขึ้นในสตริง สมมติว่าอินพุตถูกวงเล็บอย่างถูกต้องเสมอ

คุณอาจสันนิษฐานว่าอินพุตมีตัวอักษรและวงเล็บ ASCII ตัวพิมพ์เล็กเท่านั้น

คำตอบของคุณควรเป็นฟังก์ชั่นที่ส่งคืนรายการสตริง

ตัวอย่าง:

                   'a(b)c(d)e' -> ['ace', 'b', 'd']
                   'a(b(c)d)e' -> ['ae', 'bd', 'c']
                  'a((((b))))' -> ['a', 'b']
                        'a()b' -> ['ab']
                            '' -> []
                           'a' -> ['a']
          '(((a(b)c(d)e)f)g)h' -> ['h', 'g', 'f', 'ace', 'b', 'd']
'ab(c(((d)ef()g)h()(i)j)kl)()' -> ['ab', 'ckl', 'hj', 'efg', 'i', 'd']

ไบต์ที่น้อยที่สุดจะเป็นผู้ชนะ


มี'i'และ'd'อยู่ในลำดับที่ถูกต้องในกรณีทดสอบสุดท้าย?
PurkkaKoodari

@ Pietu1998 iซ้อนกันน้อยกว่าdมาก
feersum

@feersum โอ้ใช่
PurkkaKoodari

1
คุณคิดว่าจะอนุญาตให้ใช้ประเภทการส่งมาตรฐานอื่น ๆ เช่นกันในโปรแกรมเต็มรูปแบบโดยเฉพาะหรือไม่ ไม่ใช่ทุกภาษาที่มีแนวคิดเกี่ยวกับฟังก์ชั่น สำหรับการเริ่มต้นฉันทามติเห็นmeta.codegolf.stackexchange.com/a/2422/8478และmeta.codegolf.stackexchange.com/questions/2447/...
Martin Ender

2
@redstonerodent ถ้อยคำที่ฉันมักจะใช้คือ "คุณสามารถเขียนโปรแกรมหรือฟังก์ชั่น, รับอินพุตผ่าน STDIN (หรือทางเลือกที่ใกล้เคียงที่สุด), อาร์กิวเมนต์บรรทัดคำสั่งหรืออาร์กิวเมนต์ฟังก์ชันและส่งผลลัพธ์ผ่าน STDOUT (หรือทางเลือกที่ใกล้เคียงที่สุด) หรือพารามิเตอร์ของฟังก์ชัน (ออก) " และในกรณีของคุณ "เอาต์พุตอาจอยู่ในรูปแบบรายการแบบแบนที่สะดวกไม่คลุมเครือ"
Martin Ender

คำตอบ:


11

JavaScript ES6, 91 93 104 133 148

Edit2 2 ไบต์บันทึก thx user81655

แก้ไขการใช้สตริงมากขึ้นและอาร์เรย์น้อยลง

ทดสอบการเรียกใช้ตัวอย่างข้อมูลด้านล่างในเบราว์เซอร์ที่สอดคล้องกับ EcmaScript 6

f=s=>[...s].map(c=>l+=c<')'||-(o[l]=(o[l]||'')+c,c<'a'),o=[],l=0)&&(o+'').match(/\w+/g)||[]

// Less golfed

u=s=>{
  o=[]; l=0;
  [...s].map(c=>{
    if (c>'(') // letters or close bracket
      o[l]=(o[l]||'')+c, // add letter or close bracket to current level string
      l-=c<'a' // if close bracket, decrement level
    else
      ++l // open bracket, increment level
  })
  o = o+'' // collapse array to comma separated string
  return o.match(/\w+/g)||[] // fetch non empty strings into an array
}

// TEST
console.log=x=>O.innerHTML+=x+'\n'

;[ 'a(b)c(d)e'                    // ['ace', 'b', 'd']
 , 'a(b(c)d)e'                    // ['ae', 'bd', 'c']
 , 'a((((b))))'                   // ['a', 'b']
 , 'a()b'                         // ['ab']
 , ''                             // []
 , 'a'                            // ['a']
 , '(((a(b)c(d)e)f)g)h'           // ['h', 'g', 'f', 'ace', 'b', 'd']
 , 'ab(c(((d)ef()g)h()(i)j)kl)()' // ['ab', 'ckl', 'hj', 'efg', 'i', 'd']
].forEach(t=>console.log(t +" -> " + f(t)))
<pre id=O></pre>


บันทึก 2 c=>l+=c<')'||-(o[l]=(o[l]||'')+c,c<'a'),ไบต์ด้วย
user81655

@ user81655 ดีขอบคุณ
edc65

8

Julia, 117 86 83 ไบต์

v->(while v!=(v=replace(v,r"(\(((?>\w|(?1))*)\))(.*)",s"\g<3> \g<2>"))end;split(v))

มันเป็นโซลูชันของ regex

Ungolfed:

function f(v)
  w=""
  while v!=w
    w=v
    v=replace(v,r"(\(((?>\w|(?1))*)\))(.*)",s"\g<3> \g<2>"))
  end
  split(v)
end

r"(\(((?>\w|(?1))*)\))(.*)"คือ recursive ( (?1)recurses กลุ่ม 1) regex ที่จะจับคู่วงเล็บที่มีค่าสูงสุดนอกสุดตัวแรก (ที่ไม่มีวงเล็บที่ไม่สมดุล / กลับด้าน) โดยกลุ่มที่สองมีทุกอย่างที่อยู่ในวงเล็บ (ไม่รวมวงเล็บเอง) และกลุ่มที่สามที่มี ทุกอย่างหลังจากวงเล็บ (จนถึงจุดสิ้นสุดของสตริง)

replace(v,r"...",s"\g<3> \g<2>")จะย้ายกลุ่มที่สองไปยังจุดสิ้นสุดของสตริง (หลังช่องว่างเพื่อทำหน้าที่เป็นตัวคั่น) โดยลบวงเล็บที่เกี่ยวข้องออก เมื่อวนซ้ำจนถึง v == w จะทำให้มั่นใจได้ว่าการแทนที่จะถูกทำซ้ำจนกว่าจะไม่มีวงเล็บเหลืออยู่ เนื่องจากการแข่งขันถูกย้ายไปยังจุดสิ้นสุดจากนั้นการแข่งขันครั้งต่อไปจะไปสู่วงเล็บแรกผลลัพธ์จะเป็นสตริงที่แยกตามลำดับความลึก

จากนั้นsplitส่งคืนส่วนประกอบที่ไม่ใช่ช่องว่างทั้งหมดของสตริงในรูปแบบของอาร์เรย์ของสตริง (ที่ไม่มีช่องว่าง)

โปรดทราบว่าw=""มีการใช้รหัส ungolfed เพื่อให้แน่ใจว่าขณะที่ลูปทำงานอย่างน้อยหนึ่งครั้ง (ยกเว้นว่าสตริงอินพุตว่างเปล่าแน่นอน) และไม่จำเป็นในรูปแบบ golfed

ขอบคุณ Martin Büttnerสำหรับความช่วยเหลือในการประหยัด 3 ไบต์


เรียบร้อยฉันได้มาถึงโซลูชันเดียวกันอย่างอิสระในจอประสาทตา มีขนาด 44 ไบต์ แต่เนื่องจากไม่ได้รับอนุญาตให้ใช้งานโปรแกรมแบบเต็มรูปแบบ : /
Martin Ender

คุณสามารถบันทึกสามไบต์โดยใช้แทน\w [^()]
Martin Ender

@ MartinBüttner - ขอบคุณ ฉันคิดว่าจริง ๆ แล้ว แต่ฉันกังวลว่าฉันจะมองข้ามบางสิ่งและมันจะล้มเหลวในบางกรณี ถ้าคุณบอกว่าไม่เป็นไร แต่ก็ไม่เป็นไร
เกลน O

6

Python, 147 ไบต์

def f(s):
 d=0;r=[['']for c in s]
 for c in s:
  if c=='(':d+=1;r[d]+=['']
  elif c==')':d-=1
  else:r[d][-1]+=c
 return[i for i in sum(r,[])if i]

การทดสอบหน่วย:

assert f('a(b)c(d)e') == ['ace', 'b', 'd']
assert f('a(b(c)d)e') == ['ae', 'bd', 'c']
assert f('a((((b))))') == ['a', 'b']
assert f('a()b') == ['ab']
assert f('') == []
assert f('a') == ['a']
assert f('(((a(b)c(d)e)f)g)h') == ['h', 'g', 'f', 'ace', 'b', 'd']
assert f('ab(c(((d)ef()g)h()(i)j)kl)()') == ['ab', 'ckl', 'hj', 'efg', 'i', 'd']

ฉันชอบจิ๊กซอว์นี้ มันน่ารักมาก!


4

Pyth, 32 ไบต์

fTscR)uX0.<GJ-FqLH`()@[Hdk)Jzmkz

ชุดทดสอบ

อิงอย่างไม่สอดคล้องกับแนวทางของ @ Quuxplusone สร้างรายการที่คั่นด้วยช่องว่างของอักขระแต่ละระดับความลึกจากนั้นแยกออกและกรองกลุ่มที่ว่างเปล่าออก รายการการทำงานจะหมุนเพื่อเก็บรายการความลึกปัจจุบันไว้ข้างหน้าตลอดเวลา


4

เรติน่า44 44ไบต์

+`\(((\w|(\()|(?<-3>.))*).(.*)
$4 $1
S_` 

วิ่งด้วย-sธง สังเกตุที่ว่างที่ท้ายบรรทัดสุดท้าย

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

หากคุณไม่เข้าใจ regex แรกให้ฉันดูคุณจะตอบ SO ของฉันเกี่ยวกับกลุ่มสมดุล ตั้งแต่การป้อนข้อมูลที่รับประกันได้ว่าจะถูกต้องวงเล็บเราสามารถบันทึกไบต์ที่สองโดยการจับคู่)กับแทน. จากนั้นเราก็ตรงกับส่วนที่เหลือของสตริงที่มี\) ก่อนเขียนกลับกล่าวว่าส่วนที่เหลือของสตริง (ละเว้นทั้งวงเล็บและเนื้อหาของพวกเขา) แล้วเนื้อหาของวงเล็บหลังช่องว่าง The Retina บอกให้ทำซ้ำขั้นตอนนี้จนกว่าสตริงจะหยุดการเปลี่ยนแปลง (ซึ่งจะเกิดขึ้นเฉพาะเมื่อวงเล็บทั้งหมดได้ถูกลบ)(.*)$4 $1+`

วงเล็บว่างเปล่าจะส่งผลให้มีช่องว่างสองช่องติดต่อกันดังนั้นในที่สุดเราก็แยกสตริงทั้งหมดในช่องว่าง ( S`เปิดใช้งานโหมดแยกและ regex เป็นช่องว่างเดียว) _ตัวเลือกบอก Retina ที่จะละเว้นส่วนที่ว่างเปล่าของการแยกดังนั้นเราจึงไม่ได้รวมถึงผลที่ว่างเปล่าในการส่งออก


3

เสียงกระเพื่อมสามัญ 160

(lambda(x)(labels((g(l)(cons(#1=format()"~(~{~A~}~)"(#2=remove-if'listp l))(mapcan #'g(#2#'atom l)))))(remove""(g(read-from-string(#1#()"(~A)"x))):test'equal))))

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


2

Haskell, 114 112 111 bytes

')'%(h:i:t)=("":i):t++[h]
'('%l=last l:init l
c%((h:i):t)=((c:h):i):t
g x=[a|a<-id=<<foldr(%)(x>>[[""]])x,a>""]

ตัวอย่างการใช้งาน: ->g "ab(c(((d)ef()g)h()(i)j)kl)()"["ab","ckl","hj","efg","i","d"]

ฉันจะย้อนกลับผ่านสตริงอินพุต โครงสร้างข้อมูลกลางคือรายการของรายการสตริง รายการด้านนอกคือต่อระดับและรายการภายในเป็นต่อกลุ่มภายในระดับเช่น[["ab"],["ckl"],["hj"],["efg","i"],["d"]](หมายเหตุ: รายการจริงมีสตริงว่างจำนวนมากในระหว่าง) ทุกอย่างเริ่มต้นด้วยสตริงว่างจำนวนเท่ากับความยาวของอินพุต - มากเกินพอ แต่รายการที่ว่างเปล่าจะถูกกรองออกไป รายการด้านนอกหมุนหรือ(/ )เพิ่มตัวละครในองค์ประกอบด้านหน้า )ก็เริ่มกลุ่มใหม่

แก้ไข: @Zgarb พบไบต์ที่จะบันทึก


1

Sed, 90 ไบต์

:
s/^(\w*)\((.*)\n?(.*)/\1\n\3_\2/M
s/(\n\w*_)(\w*)\)(.*)/\3\1\2/M
t
s/[_\n]+/,/g
s/,$//

ใช้เรกซ์เสริม ( -rแฟล็ก) ซึ่งคิดเป็น +1 ไบต์ นอกจากนี้ยังใช้ส่วนขยาย GNU (การMตั้งค่าสถานะบนsคำสั่ง)

ตัวอย่างการใช้งาน:

$ echo 'ab(c(((d)ef()g)h()(i)j)kl)()' | sed -r -f deparenthesize.sed
ab,ckl,hj,efg,i,d

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


0

Python ขนาด 161 ไบต์

ต่อไปนี้เป็นสิ่งที่ฉันคิดไว้วิธีแก้ปัญหาแบบงูเหลือมแบบทำงานบรรทัดเดียว:

p=lambda s:filter(None,sum([''.join([s[i]for i in range(len(s))if s[:i+1].count('(')-s[:i+1].count(')')==d and s[i]!=')']).split('(')for d in range(len(s))],[]))

ความท้าทายนี้ได้รับแรงบันดาลใจจากhttps://github.com/samcoppini/Definition-bookซึ่งแสดงผลสตริงยาวที่มีคำที่กำหนดไว้ใน parentheticals ฉันต้องการเขียนโค้ดที่จะให้แต่ละประโยคกับฉันโดยลบวงเล็บ โซลูชันการทำงานช้าเกินไปที่จะมีผลบังคับใช้กับสตริงที่ยาว แต่โซลูชันที่จำเป็น (เช่นโซลูชันของ @ Quuxplusone) นั้นเร็วกว่ามาก

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