Khử ngoặc đơn


25

Đưa ra một chuỗi được ngoặc đơn đúng cách làm đầu vào, xuất ra một danh sách tất cả các chuỗi con không trống trong các dấu ngoặc phù hợp (hoặc bên ngoài tất cả các dấu ngoặc đơn), với các dấu ngoặc đơn được loại bỏ. Mỗi chuỗi con phải là chuỗi các ký tự trong ngoặc đơn khớp chính xác. Các lớp nền nên được liệt kê theo thứ tự độ sâu và các chuỗi con có cùng độ sâu phải được liệt kê theo thứ tự chúng xảy ra trong chuỗi. Giả sử đầu vào luôn được ngoặc chính xác.

Bạn có thể cho rằng đầu vào chỉ chứa các chữ cái và dấu ngoặc đơn ASCII chữ thường.

Câu trả lời của bạn phải là một hàm mà khi được cung cấp một chuỗi sẽ trả về một danh sách các chuỗi.

Ví dụ:

                   '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']

Ít byte nhất sẽ thắng.


Được 'i''d'theo đúng thứ tự trong trường hợp thử nghiệm cuối cùng?
PurkkaKoodari

@ Pietu1998 iít lồng nhau hơn d.
frageum

@feersum ơi, đúng rồi.
PurkkaKoodari

1
Bạn có phiền khi cho phép các loại trình tiêu chuẩn khác, đặc biệt là các chương trình đầy đủ không? Không phải tất cả các ngôn ngữ có một khái niệm về chức năng. Để có sự đồng thuận mặc định, hãy xem meta.codegolf.stackexchange.com/a/2422/8478meta.codegolf.stackexchange.com/questions/2447/ .
Martin Ender

2
@redstonerodent Từ ngữ tôi có xu hướng sử dụng là "Bạn có thể viết chương trình hoặc hàm, lấy đầu vào qua STDIN (hoặc thay thế gần nhất), đối số dòng lệnh hoặc đối số hàm và xuất kết quả qua STDOUT (hoặc thay thế gần nhất), giá trị trả về của hàm hoặc tham số hàm (out). " và trong trường hợp của bạn "Đầu ra có thể ở bất kỳ định dạng danh sách phẳng thuận tiện, không mơ hồ."
Martin Ender

Câu trả lời:


11

JavaScript ES6, 91 93 104 133 148

Edit2 2 byte lưu thx user81655

Chỉnh sửa Sử dụng nhiều chuỗi hơn và ít mảng hơn

Kiểm tra chạy đoạn mã dưới đây trong trình duyệt tuân thủ 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>


Lưu 2 byte với c=>l+=c<')'||-(o[l]=(o[l]||'')+c,c<'a'),.
dùng81655

@ user81655 tốt đẹp, cảm ơn
edc65

8

Julia, 117 86 83 byte

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

Đó là một giải pháp regex.

Ung dung:

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))*)\))(.*)"là một biểu thức đệ quy (đệ quy (?1)nhóm 1) sẽ khớp với dấu ngoặc đơn cân bằng ngoài cùng đầu tiên (không chứa dấu ngoặc đơn không cân bằng / đảo ngược), với nhóm thứ hai chứa mọi thứ bên trong dấu ngoặc đơn (không bao gồm dấu ngoặc đơn) và nhóm thứ ba chứa mọi thứ sau dấu ngoặc đơn (cho đến hết chuỗi).

replace(v,r"...",s"\g<3> \g<2>")sau đó sẽ di chuyển nhóm thứ hai đến cuối chuỗi (sau một khoảng trắng, để hoạt động như một dấu phân cách), với các dấu ngoặc đơn có liên quan được loại bỏ. Bằng cách lặp lại cho đến khi v == w, đảm bảo rằng sự thay thế được lặp lại cho đến khi không còn dấu ngoặc đơn. Bởi vì các trận đấu được di chuyển đến cuối cùng, và sau đó trận đấu tiếp theo diễn ra trong ngoặc đơn đầu tiên, kết quả sẽ là chuỗi được chia theo thứ tự độ sâu.

Sau đó splittrả về tất cả các thành phần không phải khoảng trắng của chuỗi dưới dạng một chuỗi các chuỗi (không có khoảng trắng).

Lưu ý rằng w=""được sử dụng trong mã không mã hóa để đảm bảo rằng vòng lặp while chạy ít nhất một lần (tất nhiên trừ khi chuỗi đầu vào trống, tất nhiên), và không cần thiết ở dạng golf.

Cảm ơn Martin Büttner đã hỗ trợ tiết kiệm 3 byte.


Không, tôi đã đến cùng một giải pháp độc lập ở Retina. Đó là 44 byte ở đó, nhưng vì nó là giải pháp toàn chương trình không được phép. : /
Martin Ender

Bạn có thể lưu ba byte bằng cách sử dụng \wthay vì [^()].
Martin Ender

@ MartinBüttner - cảm ơn. Tôi thực sự đã xem xét điều đó, nhưng tôi đã lo lắng rằng tôi đã bỏ qua điều gì đó và nó sẽ thất bại trong một số trường hợp cạnh. Nếu bạn nói nó ổn, mặc dù vậy, nó sẽ ổn thôi.
Glen O

6

Python, 147 byte

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]

Bài kiểm tra đơn vị:

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']

Tôi thích câu đố này; Thật là đáng yêu!


4

Bình thường, 32 byte

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

Bộ kiểm tra

Dựa vào cách tiếp cận của @ Quuxplusone. Xây dựng danh sách các ký tự được phân tách không gian ở mỗi độ sâu, sau đó phân tách chúng và lọc ra các nhóm trống. Danh sách làm việc được xoay để giữ danh sách độ sâu hiện tại ở phía trước mọi lúc.


4

Võng mạc , 44 41 byte

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

Chạy với -scờ. Chú ý khoảng trống ở cuối dòng cuối cùng.

Tôi đã đưa ra giải pháp này một cách độc lập với Glen O nhưng hóa ra nó giống hệt nhau. Ý tưởng là khớp cặp ngoặc đơn đầu tiên, loại bỏ nó và chèn nội dung của nó vào cuối đầu ra (lặp đi lặp lại). Do sự thiếu đệ quy của .NET trong regex, tôi đã phải sử dụng các nhóm cân bằng dài hơn bốn byte.

Nếu bạn không hiểu regex đầu tiên, hãy để tôi giới thiệu cho bạn câu trả lời SO của tôi về các nhóm cân bằng . Vì đầu vào được đảm bảo là dấu ngoặc đơn chính xác, chúng ta có thể lưu hai byte bằng cách khớp )với .thay vì \). Sau đó, chúng tôi chỉ cần khớp phần còn lại của chuỗi với (.*). $4 $1đầu tiên viết lại phần còn lại của chuỗi (bỏ qua cả dấu ngoặc đơn và nội dung của chúng), và sau đó là nội dung của dấu ngoặc sau một khoảng trắng. Lệnh +`Retina lặp lại bước này cho đến khi chuỗi ngừng thay đổi (điều này chỉ xảy ra khi tất cả các dấu ngoặc đơn đã bị xóa).

Các dấu ngoặc rỗng sẽ dẫn đến hai khoảng trắng liên tiếp, vì vậy cuối cùng chúng ta chia toàn bộ chuỗi trên các khoảng trắng ( S`kích hoạt chế độ phân tách và biểu thức chính là một khoảng trắng ). Các _tùy chọn cho Retina đến các bộ phận rỗng omit của sự chia rẽ, vì vậy chúng tôi không bao gồm các kết quả có sản phẩm nào trong đầu ra.


3

Lisp thông thường, 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))))

Đây có thể là bốn byte ít hơn nếu chuyển đổi trường hợp không cần thiết. Ý tưởng là thêm dấu ngoặc trái và phải vào mỗi bên của chuỗi đầu vào, coi nó như một danh sách, viết các phần tử mức cao nhất của danh sách vào một chuỗi, sau đó xử lý các danh sách con theo cùng một cách.


2

Haskell, 114 112 111 byte

')'%(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>""]

Ví dụ sử dụng: g "ab(c(((d)ef()g)h()(i)j)kl)()"-> ["ab","ckl","hj","efg","i","d"].

Tôi đang đi lùi qua chuỗi đầu vào. Cấu trúc dữ liệu trung gian là một danh sách các chuỗi. Danh sách bên ngoài là mỗi cấp độ và danh sách bên trong là mỗi nhóm trong một cấp độ, ví dụ [["ab"],["ckl"],["hj"],["efg","i"],["d"]](lưu ý: danh sách thực có rất nhiều chuỗi trống ở giữa). Tất cả bắt đầu với một số chuỗi trống bằng với độ dài của đầu vào - quá đủ, nhưng danh sách trống vẫn được lọc ra. Các danh sách bên ngoài hoặc xoay trên (/ )hoặc thêm ký tự vào phần tử phía trước. )cũng bắt đầu một nhóm mới.

Chỉnh sửa: @Zgarb đã tìm thấy một byte để lưu.


1

Sed, 90 byte

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

Sử dụng biểu thức chính mở rộng ( -rcờ), chiếm 1 byte. Ngoài ra, điều này sử dụng một phần mở rộng GNU ( Mcờ trên slệnh).

Sử dụng mẫu:

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

Giải thích: Vì sed không hỗ trợ các công cụ như regex đệ quy, nên công việc thủ công là bắt buộc. Biểu thức được chia thành nhiều dòng, mỗi dòng đại diện cho một mức độ sâu lồng nhau. Các biểu thức riêng lẻ trên cùng một độ sâu (và do đó trên cùng một dòng) được phân tách bằng một _. Kịch bản hoạt động thông qua một chuỗi đầu vào một khung tại một thời điểm. Đầu vào còn lại luôn được giữ ở cuối dòng tương ứng với mức lồng nhau hiện tại.


0

Python, 161 byte

Đây là những gì tôi nghĩ ra, một giải pháp python chức năng một dòng:

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))],[]))

Thử thách này được lấy cảm hứng từ https://github.com/samcoppini/DefDef-book , đưa ra một chuỗi dài với từ được định nghĩa trong ngoặc đơn. Tôi muốn viết mã sẽ cung cấp cho tôi mỗi câu, với dấu ngoặc đơn được loại bỏ. Giải pháp chức năng quá chậm để có hiệu quả trên các chuỗi dài, nhưng các giải pháp bắt buộc (như giải pháp của @ Quuxplusone) nhanh hơn nhiều.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.