Tìm trận đấu khung đầu tiên


22

Đây là một trong một loạt các thử thách dẫn đến sinh nhật của Brain-Flak. Tìm hiểu thêm ở đây .

Thử thách

Đối với thử thách này, mục tiêu của bạn sẽ là tìm ra cặp dấu ngoặc đầu tiên trong chuỗi ()[]{}<>dấu ngoặc khớp hoàn toàn . Để mượn định nghĩa của DJMcMayhem về một chuỗi hoàn toàn khớp:

  • Đối với mục đích của thử thách này, "khung" là bất kỳ ký tự nào trong số này : ()[]{}<>.

  • Một cặp ngoặc được coi là "khớp" nếu dấu ngoặc mở và đóng theo đúng thứ tự và không có ký tự bên trong chúng, chẳng hạn như

    ()
    []{}
    

    Hoặc nếu mọi phân lớp bên trong của nó cũng được khớp.

    [()()()()]
    {<[]>}
    (()())
    

    Subelements cũng có thể được lồng nhiều lớp sâu.

    [(){<><>[()]}<>()]
    <[{((()))}]>
    
  • Một chuỗi được coi là "Hoàn toàn khớp" khi và chỉ khi mỗi cặp dấu ngoặc có dấu mở và đóng đúng theo thứ tự đúng.

Đầu vào

Đầu vào sẽ bao gồm một chuỗi không trống hoặc mảng char chỉ chứa các ký tự ()[]{}<>và được đảm bảo khớp hoàn toàn. Bạn có thể nhận đầu vào theo bất kỳ cách hợp lý nào tương ứng với mặc định i / o của chúng tôi .

Đầu ra

Đầu ra của chương trình hoặc chức năng của bạn sẽ là chỉ mục của khung đóng cái đầu tiên. Đầu ra phải được 0hoặc 1được lập chỉ mục. Một lần nữa, đầu ra có thể theo bất kỳ cách hợp lý nào tương ứng với mặc định i / o của chúng tôi .

Các trường hợp thử nghiệm

Input       0-indexed   1-indexed
()          1           2
(<>)        3           4
<[]{<>}>    7           8
{}{}{}{}    1           2
[[]<>[]]    7           8

Đây là , ít byte thắng nhất!


3
Điểm thưởng nếu bạn trả lời trong Brain-Flak ofc :)
Erik the Outgolfer

1
@EriktheOutgolfer Xong
DJMcMayhem

1
Kỹ thuật này rất hữu ích để viết các triển khai BF không hiệu quả.
Trái cây Esolanging

Câu trả lời:


2

V , 4 byte

%Dø.

Hãy thử trực tuyến!

Điều này, không giống như hầu hết các câu trả lời V, sử dụng lập chỉ mục 0. Tôi vô cùng tự hào về câu trả lời này, và ngôn ngữ của tôi đã đi được bao xa. Giải trình:

%       " Jump to the first bracket match
 D      " Delete everything under and after the cursor
  ø     " Count the number of times the following regex is matched:
   .    "   Any character

Không có bản soạn sẵn mà bạn cần để khớp <>?
Pavel

@Pavel Trong vim, vâng. Nhưng không phải ở V.
DJMcMayhem

27

Brain-Flak , 685, 155, 151 , 137 byte

(())({<{}({}()<(()()()())>)({}(<>))<>{(({})){({}[()])<>}{}}{}<>
([{}()]{})(({})){{}({}[()])(<()>)}{}(<>)<>{{}<>{}({}<>)}{}(<>[]<>)>()}<>)

Hãy thử trực tuyến!

136 byte mã, cộng với một byte cho -a. Một chỉ mục.

530 byte đánh gôn! Đó có lẽ là sân golf lớn nhất tôi từng làm.

14 byte được lưu nhờ Riley!

Điều này lạm dụng một công thức của dấu ngoặc đơn đóng / mở: nếu bạn lấy các giá trị ASCII, tăng nó lên một và lấy modulo bằng 4, các trình mở ( ({[<) sẽ luôn nhận được 0hoặc 1, trong khi các trình đóng ( )}]>) sẽ luôn nhận được 2 hoặc 3.

Giải trình:

#Push 1
(())

#While true
({<

    #Pop stack height
    {}

    #Compute (TOS + 1) % 4
    ({}()<(()()()())>)({}(<>))<>{(({})){({}[()])<>}{}}{}<>([{}()]{})

    #Decrement if positive
    (({})){{}({}[()])(<()>)}{}

    #Push 0 onto alternate
    (<>)

    #Toggle back
    <>

    #Pop two zeros from alternate if closer
    {{}<>{}({}<>)}{}

    #Push height of alternate stack
    (<>[]<>)

#Make each time through evaluate to 1
>()

#Endwhile
}

#Push the number of loops onto the offstack
<>)

8
Đối với tình yêu của Thiên Chúa, những gì trên trái đất này.
Leaky Nun

Về cơ bản mọi người hiện đang sử dụng n-1&2/ n+1&2/ -n&2hoặc n%7&2để phân biệt dấu ngoặc mở và đóng ...
ETHproductions

@ETHproductions Tôi không chắc liệu bộ não có thể tính toán hiệu quả hay không &2, nhưng tôi sẽ xem xét nó.
DJMcMayhem

Ồ, tôi nghĩ bạn là. Bạn phải làm điều gì đó tương tự để phân biệt giữa 0/ 12/ 3... mặc dù bây giờ tôi nhìn vào nó, bạn chỉ đang giảm nếu tích cực. Một mẹo hay cũng là :-)
ETHproductions

1
(TOS+1)%4thể ngắn hơn: Hãy thử trực tuyến!
MegaTom

11

05AB1E , 17 16 10 byte

-1 nhờ tính toán

-6 cảm ơn Adnan vì cái nhìn sâu sắc tuyệt vời của anh ấy rằng "sau khi tăng, bit cuối cùng thứ hai là 0 cho khung mở và 1 cho khung đóng"

Ç>2&<.pO0k

Hãy thử trực tuyến!

Ç          # Get input as ASCII values
 >         # Increment
  2&       # And with 2 (0 for open and 2 for close brackets)
    <      # decrement 
     .p    # prefixes
       O   # Sum
        0k # Print the index of the first 0

žudường như có thể sử dụng ở đây.
Bạch tuộc ma thuật Urn

žu8ÝÈÏvì vậy, không, không thực sự lol. Tốt nhất nó vẫn sẽ là 5 byte. Tôi đã suy nghĩ nhiều hơn về việc chia thành các cặp niềng răng và loại bỏ niềng răng cho đến khi chỉ còn một cặp, bộ đếm tăng thêm 2 cho mỗi cặp bị loại bỏ. Tôi không biết nếu đó là ít hơn mặc dù. Đang thử nó atm.
Bạch tuộc ma thuật Urn

Đối với 10 byte : Ç>2&<.pO0k.
Ad Nam

1
Chỉ loay hoay với các giá trị ASCII. Lưu ý rằng sau khi tăng, bit cuối cùng thứ hai là 0cho khung mở và 1cho khung đóng.
Ad Nam

11

Vim, 23 byte

:se mps+=<:>
%DVr<C-a>C1<esc>@"

Hãy thử trực tuyến!

Tôi thực sự buồn về câu trả lời này. Giải pháp này rất đẹp và thanh lịch, nhưng theo mặc định, vim không xem xét <>để được khớp, vì vậy tôi cần 13 byte mã soạn sẵn. Nếu không, đây sẽ chỉ là 10 byte.

Tôi đã đăng một câu trả lời V, nhưng nó sẽ chỉ ngắn hơn một byte, cụ thể là thay đổi Vrthành Ò, vì đó Vrlà một thành ngữ vim phổ biến.

Đây là 1 chỉ mục nhưng có thể được sửa đổi một cách tầm thường thành 0 chỉ mục bằng cách thay đổi 1thành a 0.

:se mps+=<:>        " Stupid boilerplate that tells vim to consider `<` and `>` matched
%                   " Jump to the bracket that matches the bracket under the cursor
 D                  " Delete everything from here to the end of the line
  V                 " Visually select this whole line
   r<C-a>           " Replace each character in this selection with `<C-a>`
                    " This conveniently places the cursor on the first char also
         C          " Delete this whole line into register '"', and enter insert mode
          1<esc>    " Enter a '1' and escape to normal mode
                @"  " Run the text in register '"' as if typed. Since the `<C-a>` command
                    " Will increment the number currently under the cursor

1
Đăng câu trả lời V sau đó :)
Erik the Outgolfer

10

Thạch , 11 10 9 byte

O’&2’+\i0

Hãy thử trực tuyến!

Giải trình

Ý tưởng ở đây là tìm ra một "công thức ma thuật" có thể phân biệt việc mở với đóng ngoặc. Ban đầu tôi đã sử dụng O%7&2(nghĩa là "lấy mã ASCII, modulo 7, bitwise-và 2"), nhưng @ETHproductions đã đề xuất O’&2(thay thế modulo 7 bằng một phần giảm); cả hai trả về 0 cho một loại khung và 2 cho loại kia. Trừ đi 1 ( ) sẽ biến các kết quả này thành -1 và 1.

Phần còn lại của mã là +\. +\tạo ra một tổng tích lũy. Nếu một tập hợp dấu ngoặc được khớp chính xác, nó sẽ chứa cùng số -1 và 1, tức là tổng tích lũy của nó sẽ là 0. Sau đó, chúng ta chỉ cần trả về chỉ số của 0 đầu tiên trong danh sách kết quả; chúng ta có thể làm điều đó với i0.


Hấp dẫn như thế nào chúng tôi đã thực hiện một cách tiếp cận tương tự để phát hiện dấu ngoặc đóng. Thật không may, tôi chỉ tìm thấy một phiên bản kém hơn:b*2%7>3
2501

Cách tiếp cận thú vị! Tôi đã phát triển một câu trả lời dài hơn (để thực hành) mà cuối cùng tôi đã đánh golf để thực tế điều này, ngoại trừ đủ thú vị, thay vì giảm đầu tiên trong bài viết của bạn, thay vào đó tôi đã tăng lên. :)
HyperNeutrino

9

Võng mạc , 26 24 byte

M!`^.(?<-1>([[({<])*.)*

Hãy thử trực tuyến!

Kết quả là 1 dựa trên.

Giải trình

Một giải pháp Retina rất khác về cơ bản dựa trên một biểu thức chính (và rất dễ đọc ...). Điều này sử dụng một kỹ thuật mới mà tôi đã phát hiện ra ngày hôm qua để khớp các chuỗi cân bằng bằng cách sử dụng các nhóm cân bằng .

M!`^.(?<-1>([[({<])*.)*

Tìm ( M) và trả lại ( !) tất cả các kết quả khớp của biểu thức chính quy ^.(?<-1>([[({<])*.)*. Regex đó bỏ qua ký tự đầu tiên của chuỗi và sau đó sử dụng các nhóm cân bằng để theo dõi độ sâu làm tổ. Bất kỳ việc [({<tăng độ sâu (theo dõi theo nhóm 1) và bất kỳ ký tự nào khác đều làm giảm độ sâu (về nguyên tắc, .cho phép giảm độ sâu bằng cách mở dấu ngoặc, nhưng vì regex được khớp một cách tham lam, nên người quay lại sẽ không bao giờ thử ). Thủ thuật kỳ lạ là (?<-1>...)nhóm bao vây 1hoạt động vì sự xuất hiện từ một nhóm cân bằng xảy ra ở cuối nhóm. Điều này tiết kiệm hai byte theo cách tiếp cận tiêu chuẩn trong biểu mẫu((open)|(?<-2>close))*. Trận đấu nhất thiết phải dừng ở khung đóng cái đầu tiên, vì chúng tôi đã bỏ qua nó, vì vậy nó không được tính vào độ sâu ngăn xếp (và độ sâu của ngăn xếp không thể âm).

Độ dài của trận đấu này là chỉ số dựa trên 0 của khung mà chúng tôi đang tìm kiếm.


Đơn giản chỉ cần đếm số lượng trận đấu trống trong chuỗi này. Regex trống luôn khớp một lần nữa so với các ký tự trong chuỗi, do đó, điều này mang lại cho chúng ta chỉ số dựa trên 1 của dấu ngoặc mà chúng ta đang tìm kiếm.


Thật tuyệt vời!
Pavel

Cách tiếp cận ngắn hơn : xóa phần thứ hai của chuỗi thay vì khớp với phần thứ nhất. Tôi thích cách bạn đo chiều dài của chuỗi, btw!
Leo

@Leo Thật là gọn gàng! Bạn có thể đăng câu đó dưới dạng câu trả lời riêng :)
Martin Ender

Ok, thủ thuật mới này cho các chuỗi cân bằng là tuyệt vời: D
Leo

6

Võng mạc , 24 byte

.(([[({<])|(?<-2>.))*$


Hãy thử trực tuyến!

Điều này được lấy cảm hứng từ giải pháp của Martin Ender .

Giải trình

Dòng đầu tiên là một biểu thức khớp với một ký tự được theo sau bởi một chuỗi cân bằng đi đến hết chuỗi chính (để giải thích chi tiết về cách các nhóm cân bằng được sử dụng trong biểu thức này xem câu trả lời của Martin). Vì các biểu thức tìm kiếm các kết quả khớp từ trái sang phải, nên điều này sẽ tìm thấy một tiền tố phù hợp cân bằng dài nhất, đó là tất cả mọi thứ sau dấu ngoặc đóng cái đầu tiên, cộng với chính dấu ngoặc.

Dòng sau trống, vì vậy chúng tôi thay thế kết quả khớp bằng một chuỗi trống, có nghĩa là bây giờ chúng tôi chỉ cần đếm các ký tự còn lại để có kết quả mong muốn (được lập chỉ mục 0).

Dòng trống cuối cùng đếm số lượng khớp của chuỗi trống trong chuỗi, nhiều hơn một số ký tự trong chuỗi, tương đương với kết quả 1 chỉ mục.


Tôi tìm thấy một kỹ thuật mới cho phù hợp với chuỗi sự cân ngày hôm qua đó tiết kiệm hai byte trên cả các câu trả lời của chúng tôi: tio.run/##K0otycxL/K@q4Z7wX0/D3kbX0E4jOlqj2iZWU0tPU0uFi@v/... (và có lẽ một tá những người khác mà tôi đã viết trong quá khứ ...)
Martin Ender

5

Perl 5 , 28 byte

Đã lưu 6 byte bằng cách sử dụng .thay vì [>})\]], từ câu trả lời Retina của Martin Ender .

27 byte mã + -pcờ.

/([<{([](?0)*.)+?/;$_=$+[0]

Hãy thử trực tuyến!

Regex đệ quy, những gì một phát minh đẹp.
Regex tìm kiếm một dấu ngoặc mở ( [<{([]), theo sau là cuộc gọi đệ quy ( ?0), theo sau là dấu ngoặc đóng ( .). Tất cả điều này không tham lam ( +?) vì vậy nó phù hợp càng ngắn càng tốt ngay từ đầu. Chỉ số kết thúc trận đấu là câu trả lời, và khi nó xảy ra, nó có thể được tìm thấy trong $+[0].


4

JavaScript (ES6), 55 53 52 byte

Đã lưu 1 byte nhờ @Adnan

f=([c,...s],i=1)=>(i-=-c.charCodeAt()&2)&&1+f(s,++i)

Đối với mỗi khung mở, lấy mod char-code 4 của nó cho chúng ta 0 hoặc 3; đối với dấu ngoặc đóng, nó cung cấp cho chúng ta 1 hoặc 2. Do đó, chúng ta có thể phân biệt giữa mở và đóng dấu ngoặc bằng cách phủ định mã char của dấu ngoặc (lật các bit và trừ 1) và lấy bit có trọng số thấp thứ hai; có nghĩa là, n&2.


Tôi nghĩ rằng thay vì n-1&2, -n&2cũng làm việc?
Ad Nam

@Ad Nam Hmm, tôi nghĩ bạn đúng. Cảm ơn!
Sản phẩm ETH

4

C, 75 72 56 55 54 45 byte

a;f(char*s){return(a-=(-*s++&2)-1)?1+f(s):0;}

Nhìn thấy nó hoạt động trực tuyến .

Nếu bạn muốn đầu ra được lập chỉ mục 1 thay vì chỉ mục 0, hãy thay thế cuối cùng 0bằng 1.


4

Python 2.7 + Numpy, 85 79 byte

Nỗ lực đầu tiên của tôi tại mã golf:

from numpy import*
lambda s:list(cumsum([(ord(x)+1&2)-1for x in s])).index(0)

1
Chào mừng đến với trang web!
DJMcMayhem

1
Bạn không phải đặt tên lambdas, bạn có thể xóa g =
Pavel

4

Brain-Flak , 97 byte (96 cho mã, 1 cho cờ)

{}<>(())({<(<()>)<>({<({}[()])><>([{}]())<>}{})<>(<{}>())<>{({}[()])<>([{}])<>}{}<>({}{})>()}{})

Chạy với -acờ.

Hãy thử trực tuyến!

Giải trình:

#Skip the first open bracket 
{}

#Place a 1 on stack B, representing the nesting depth
<>(())

#Start a loop, until the depth is 0
({<

 #Divide the ASCII code by 2, rounding up
 (<()>)<>({<({}[()])><>([{}]())<>}{})<>

 #Replace TOS B with a 1
 (<{}>())

 #Swap back to stack A
 <>

 #Negate the 1 on stack B n times (n = ASCII value+1/2)
 {({}[()])<>([{}])<>}{}

 #Swap back to stack B
 <>

 #Add the 1/-1 (depending on Open/close bracket) to the nesting depth accumulator
 ({}{})

 #Count loop cycles
 >()

#end loop, print result implicitly by pushing to the stack 
}{}) 

Nó chỉ hoạt động, được thôi.


3

Võng mạc , 34 byte

^.
!
T`([{}])`<<<>
+T`p`!`<!*>
\G!

Hãy thử trực tuyến!

Kết quả là dựa trên 0.

Giải trình

^.
!

Thay thế ký tự đầu tiên bằng a !. Điều này khiến cho khung mà chúng tôi đang tìm kiếm không thể so sánh được.

T`([{}])`<<<>

Chuyển đổi dấu ngoặc đơn, dấu ngoặc vuông và dấu ngoặc nhọn thành dấu ngoặc góc. Vì chuỗi được đảm bảo khớp hoàn toàn, chúng tôi không quan tâm đến các loại thực tế và điều này sẽ tiết kiệm một số byte trong bước tiếp theo.

+T`p`!`<!*>

Lặp lại ( +) thay thế từng ký tự trong tất cả các kết quả <!*>bằng !s. Đó là, chúng tôi khớp các cặp dấu ngoặc không chứa dấu ngoặc chưa được xử lý và biến chúng thành dấu chấm than tiếp theo. Điều này sẽ biến toàn bộ chuỗi ngoại trừ khung đóng chưa từng có thành dấu chấm than.

\G!

Đếm số dấu chấm than hàng đầu, bằng với vị trí dựa trên 0 của dấu không dấu chấm than đầu tiên (nghĩa là dấu ngoặc không khớp). Các \Gneo từng khớp với cái trước đó, đó là lý do tại sao điều này không tính !s sau khung đã nói.


Tôi thấy bạn đã trả lời trên trang chủ và biết rằng nó sẽ sử dụng một loại regex nào đó
Christopher

@Christopher Eh, cái này hầu như không sử dụng bất kỳ regex nào cả (trái ngược với câu trả lời Retina khác tôi vừa đăng ...).
Martin Ender

Sheesh. Regex nhiều?
Christopher

Tại sao điều này không hoạt động?
Leaky Nun

@LeakyNun Vì (?!(2))chỉ là (?!2). Bạn có thể có nghĩa là (?(2)(?!))hoặc (?2)!). Bạn cũng quên thoát một ]và cuối cùng +cần phải có *.
Martin Ender

2

PHP, 116 byte

for($l=["("=>")","["=>"]","{"=>"}","<"=>">"][$f=$argn[0]];;$d>0?$i++:die("$i"))$d+=$f!=($n=$argn[$i])?$n==$l?-1:0:1;

Phiên bản trực tuyến


Không cần PHP để bắt đầu <?php?
Pavel

@Phoenix: Có một trình thông dịch PHP độc lập không yêu cầu thẻ bắt đầu. Đó là những gì thường được sử dụng để chơi golf.

@ ais523 Trong trường hợp này PHP chạy từ dòng lệnh với tùy chọn -R
Jörg Hülsermann

2

Python , 76 byte

f=lambda s,r=[],i=0:(i<1or sum(r))and f(s[1:],r+[(ord(s[0])+1&2)-1],i+1)or i

Hàm đệ quy sử dụng LSB thứ 2 làm cờ cho thủ thuật mở so với đóng được sử dụng bởi nhiều người được tìm thấy bởi Adnan (và có thể là những người khác). Đuôi trúng khi tổng tích lũy của -1mở và 1đóng gần bằng không. Chỉ mục được giữ trong một biến vì nó rẻ hơn byte so với sử dụng len(r), lập chỉ mục là dựa trên 1.

Hãy thử trực tuyến!


2

Hồng ngọc, 35 34 byte

p$_[/[<{(\[](\g<0>)*[>})\]]/].size

Dựa trên câu trả lời Perl5 của Dada . Đầu ra là 1 chỉ mục. Yêu cầu trình thông dịch Ruby được gọi với -ntùy chọn ( while getsvòng lặp ẩn ).

Chỉnh sửa: Đây cũng là 35 34 byte, nhưng là một điểm khởi đầu có thể khác để giảm câu trả lời này hơn nữa.

p$_[/[<{(\[](\g<0>)*[>})\]]/]=~/$/

Edit2: Đã xóa các khoảng trống không cần thiết sau p.

Edit3: Một vài câu trả lời 34 byte.

~/[<{(\[](\g<0>)*[>})\]]/;p$&.size
p~/[<{(\[](\g<0>)*[>})\]]/+$&.size

2
Chào mừng đến với PPCG!
Pavel

1
Nhiều đánh giá cao! :)
Ray Hamel

2

Python 3 , 59 55 50 49 byte

f=lambda s,n=1:n and-~f(s[1:],n+1-(-ord(s[1])&2))

Đầu ra là 0-index. Công thức để xác định hướng khung được phát hiện đầu tiên bởi @ETH Productstions và được cải thiện bởi @Adnan.

Hãy thử trực tuyến!


1

Mẻ, 172 byte

@set/ps=
@set/ai=d=0
:l
@set/ai+=1,d-=1
@set c="%s:~,1%"
@set "s=%s:~1%
@for %%a in ("<" "(" "[" "{")do @if %%a==%c% set/ad+=2&goto l
@if %d% gtr 0 goto l
@echo %i%

1 chỉ mục. <>Tất nhiên chúng là những ký tự đặc biệt trong Batch vì vậy tôi không chỉ phải trích dẫn khắp nơi mà thậm chí tôi còn không thể thực hiện các thủ thuật như biến chúng thành gotonhãn.


1

R, 126 byte

s=readline();i=0;r=0;for(c in strsplit(s,"")[[1]]){if(grepl("[\\[\\(\\{<]",c))i=i+1 else i=i-1;if(i==0){print(r);break};r=r+1}

0

C, 127 byte

Thử trực tuyến

c(x){x-40&x-60&x-91&x-123?-1:1;}
f(i,t)char*t;{return i?f(i+c(*t),t+1):t;}
s(char*t){return f(c(*t),t+1)-t;}

Đầu ra

2   ()
4   (<>)
8   <[]{<>}>
2   {}{}{}{}
8   [[]<>[]]

Bất kỳ bình luận, downvoter.
Khaled.K

Tôi không phải là người hạ cấp, nhưng tôi không nghĩ rằng nó đã giúp trình C được rút ngắn hơn nhiều.
Ørjan Johansen
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.