最初のブラケットマッチを見つける


22

これは、Brain-Flakの誕生日に至る一連の課題の1つでした。詳細はこちらをご覧ください

チャレンジ

この課題の目的は、完全に一致するブラケットの文字列から一致するブラケットの最初のペアを見つけること()[]{}<>です。完全に一致する文字列のDJMcMayhemの定義を借用するには:

  • この課題のために、「括弧」は次の文字のいずれかです()[]{}<>

  • 次のように、開始ブラケットと終了ブラケットが正しい順序であり、その中に文字がない場合、一対のブラケットは「一致」とみなされます。

    ()
    []{}
    

    または、その中のすべてのサブ要素も一致する場合。

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

    サブエレメントは、いくつかのレイヤーの深さにネストすることもできます。

    [(){<><>[()]}<>()]
    <[{((()))}]>
    
  • ブラケットの各ペアに正しい順序で正しい開始ブラケットと終了ブラケットがある場合にのみ、文字列は「完全一致」と見なされます。

入力

入力は、文字のみを含む単一の空でない文字列またはchar配列で構成()[]{}<>され、完全に一致することが保証されます。I / Oデフォルトに対応する合理的な方法で入力を行うことができます。

出力

プログラムまたは関数の出力は、最初の括弧を閉じる括弧のインデックスになります。出力01インデックス化されているか、どちらかでなければなりません。繰り返しますが、出力はi / oのデフォルトに対応する合理的な方法で行われます。

テストケース

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

これは、最少バイトが勝ちます!


3
Brain-Flak ofcで回答するとボーナスポイント:)
エリックアウトゴルファー

1
@EriktheOutgolfer 完了
DJMcMayhem

1
この手法は、BFの非効率的な実装を記述するのに非常に役立ちます。
エソランジングフルーツ

回答:


2

V、4バイト

%Dø.

オンラインでお試しください!

これは、ほとんどのV回答とは異なり、0インデックスを使用します。私はこの答えを非常に誇りに思っており、私の言語がどこまで来たかを誇りに思っています。説明:

%       " 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

<>のマッチングに必要な定型文はありませんか?
パベル

@Pavel vimでは、はい。しかし、ではないV.中
DJMcMayhem

27

Brain-Flak685、155、151、137バイト

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

オンラインでお試しください!

136バイトのコードに加えて、1バイト-a。1つはインデックス付き。

530バイトが飛び出しました!それはおそらく私が今までにした最大のゴルフでしょう。

ライリーのおかげで14バイトが節約されました!

これは開始/終了括弧の式を乱用します:ASCII値を取得し、それを1増やし、モジュロ4を取得すると、オープナー(({[<)は常に0またはを取得します1が、クローザー()}]>)は常に2または3を取得します。

説明:

#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
神の愛のために、これは一体何なのか。
リーキー修道女

基本的には誰もが今使っているn-1&2/ n+1&2/ -n&2またはn%7&2開閉ブラケットを区別するために...
ETHproductions

@ETHproductions brain-flakが効率的に計算できるかどうかはわかりません&2が、調査します。
DJMcMayhem

ああ、私はあなたがいたと思いました。あなたは0/ 12/ を区別するために似たようなことをしているに違いありません3...しかし、今私はそれを見ると、あなたは正であれば減少しているだけです。クールなトリックも:
ETHproductions

1
(TOS+1)%4短くすることができる:オンラインそれをお試しください!
メガトム

11

05AB1E17 16 10バイト

-1 carusocomputingに感謝

-6「増分後、最後の2番目のビットは開始ブラケットの場合は0、終了ブラケットの場合は1」という驚くべき洞察に感謝します。

Ç>2&<.pO0k

オンラインでお試しください!

Ç          # 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

žuここで使用できるようです。
魔法のタコUr

žu8ÝÈÏだから、いや、本当に笑いません。せいぜい5バイトのままです。私はブレースのペアにさらに分割し、残りのペアが1つだけになるまでブレースを削除し、削除されたペアごとにカウンタを2増やします。それが少ないかどうかはわかりません。ATMを試してみてください。
魔法のタコUr

10のバイト:Ç>2&<.pO0k
アドナン

1
ASCII値をいじるだけです。インクリメント後、最後から2番目のビットは0開始ブラケット1用と終了ブラケット用であることに注意してください。
アドナン

11

Vim、23バイト

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

オンラインでお試しください!

私はこの答えについて本当に悲しいです。このソリューションは、デフォルトでは、Vimは考慮していない、美しくエレガントで短いですが、<>私は定型的なコードの13バイトを必要とするので、一致させます。それ以外の場合、これはちょうど10バイトになります。

すなわち変更、私はVの答えを掲載しているだろうが、それは1バイトのみ短くなりVrÒあるため、Vr共通のvim-イディオムです。

これは、1インデックスであるが、些細な変化によって0インデックスされるように改変され得る1Aに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
その後、Vの回答を投稿してください:)
エリックアウトゴルファー

10

ゼリー11 10 9バイト

O’&2’+\i0

オンラインでお試しください!

説明

ここでのアイデアは、開き括弧と閉じ括弧を区別できる「魔法の式」を見つけることでした。私はもともと使用していましたO%7&2(つまり、ASCIIコード、モジュロ7、ビット単位、および2を使用)が、@ ETHproductionsが提案しましたO’&2(モジュロ7をデクリメントに置き換えます)。どちらも、ある種のブラケットに対して0を返し、別の種類に対して2を返します。1()を引くと、これらの結果が-1と1になります。

残りのコードは+\です。+\累積合計を生成します。ブラケットのセットが正しく一致する場合、同数の-1と1が含まれます。つまり、累積合計は0になります。その後、結果リストの最初の0のインデックスを返すだけです。でそれを行うことができますi0


閉じかっこを検出するために同様のアプローチをどのように取ったかが興味深い。:残念ながら、私は劣るバージョン見つかったb*2%7>3
2501年

興味深いアプローチ!長い答えを(練習用に)作成しましたが、最終的に実際にこれに絞り込みました。興味深いことに、投稿の最初の減分の代わりに、代わりに増分がありました。:)
HyperNeutrino

9

網膜26 24バイト

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

オンラインでお試しください!

結果は1ベースです。

説明

本質的に単一の(そして非常に読みやすい...)正規表現に基づいた、非常に異なるRetinaソリューション。これは、バランスグループを使用してバランスの取れた文字列を一致させるために昨日発見した新しい手法を使用しています

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

正規表現のすべての一致を見つけて(M)返します。その正規表現は、文字列の最初の文字をスキップしてから、バランスグループを使用して、ネストの深さを追跡します。深さの増加(グループごとの追跡)および他のキャラクターの深さの減少(原則として、括弧を開くことで深さも減少できますが、正規表現は貪欲に一致するため、バックトラッカーはそれを試みません)。奇妙なトリックは、バランスグループからのポップがグループの最後で発生するために動作するグループを囲むことです。これにより、次の形式の標準的なアプローチよりも2バイト節約できます。!^.(?<-1>([[({<])*.)*[({<1.(?<-1>...)1((open)|(?<-2>close))*。マッチは、最初のブラケットをスキップしたブラケットで終了するため、必然的に停止します。したがって、スタックの深さは考慮されません(そして、スタックの深さは負になりません)。

この一致の長さは、探しているブラケットの0から始まるインデックスです。


この文字列で空の一致の数を単純に数えます。空の正規表現は、常に文字列に文字があるよりも1回だけ一致するため、探しているブラケットの1から始まるインデックスが得られます。


そりゃ素晴らしい!
パベル

より短いアプローチ:最初の部分と一致する代わりに、文字列の2番目の部分を削除します。ところで、弦の長さの測定方法が気に入っています。
レオ

@レオそれは本当にすてきです!別の回答として投稿できます:)
マーティンエンダー

わかりました、バランスの取れた弦のこの新しいトリックは素晴らしいです:D-
レオ

6

網膜、24バイト

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


オンラインでお試しください!

これは、Martin Enderのソリューションに触発されています

説明

最初の行は、文字に一致する正規表現で、その後にメイン文字列の最後までバランスの取れた文字列が続きます(この正規表現でのバランシンググループの使用方法の詳細については、Martinの答えを参照してください)。正規表現は一致を左から右に探すため、最も長いバランスのとれた適切なサブフィックス、つまり、最初のものを閉じるブラケットとブラケット自体の後にあるものすべてを見つけます。

次の行は空なので、一致を空の文字列に置き換えます。つまり、残りの文字を数えるだけで、(0から始まる)望ましい結果が得られます。

最後の空行は、文字列内の空文字列の一致数をカウントします。これは、1インデックスの結果に相当する文字列内の文字数よりも1つ多くなります。


:私は、私たちの答えの両方に2つのバイトを保存し、昨日バランスの取れた文字列をマッチングするための新しい手法見つけtio.run/##K0otycxL/K@q4Z7wX0/D3kbX0E4jOlqj2iZWU0tPU0uFi@v/...(と私が書いた、おそらくダース他のものを過去...)
マーティンエンダー

5

Perl 5、28バイト

Martin EnderのRetina answer.代わりに[>})\]]、を使用するだけで6バイトを節約しました。

27バイトのコード+ -pフラグ。

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

オンラインでお試しください!

再帰正規表現、なんて美しい発明か。
正規表現は、開き括弧([<{([])、再帰呼び出し?0)、閉じ括弧(.)の順に探します。このすべてが貪欲ではない(+?)ため、最初から可能な限り短く一致します。マッチの終わりのインデックスは答えであり、それが起こると、それはで見つけることができます$+[0]


4

JavaScript(ES6)、55 53 52バイト

@Adnanのおかげで1バイト節約

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

すべての開始ブラケットについて、char-code mod 4を使用すると0または3が得られます。閉じ括弧については、1または2が得られます。したがって、括弧の文字コード(ビットを反転して1を減算)を否定し、2番目の最下位ビットを取得することで、開き括弧と閉じ括弧を区別できます。つまり、n&2


私が代わりにそれを考えてn-1&2-n&2また動作しますか?
アドナン

@Adnanうーん、あなたは正しいと思う。ありがとう!
-ETHproductions

4

C、75 72 56 55 54 45バイト

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

オンラインでご覧ください。

出力を0インデックスではなく1インデックスにする場合は、最後0をで置き換えます1


4

Python 2.7 + Numpy、85 79バイト

コードゴルフでの私の最初の試み:

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

1
サイトへようこそ!
DJMcMayhem

1
ラムダに名前を付ける必要はありません。g=を削除できます。-
パベル

4

Brain-Flak、97バイト(コードの場合は96、フラグの場合は1)

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

-aフラグを指定して実行します。

オンラインでお試しください!

説明:

#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 
}{}) 

うまくいきます


3

網膜、34バイト

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

オンラインでお試しください!

結果は0ベースです。

説明

^.
!

最初の文字をに置き換え!ます。これにより、探しているブラケットが一致しなくなります。

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

かっこ、角かっこ、かっこを山かっこに変換します。文字列は完全に一致することが保証されているため、実際の型はまったく気にしません。これにより、次のステップでいくつかのバイトが節約されます。

+T`p`!`<!*>

繰り返し(+)のすべての一致の各文字<!*>!sに置き換えます。つまり、さらに処理されていないブラケットを含まないブラケットのペアを照合し、それらをさらなる感嘆符に変換します。これにより、一致しない閉じ括弧を除く文字列全体が感嘆符に変わります。

\G!

先頭の感嘆符の数をカウントします。これは、最初の非感嘆符(つまり、一致しない括弧)の0から始まる位置に等しくなります。\Gアンカーはそれぞれ前のアンカーと一致するため、この!括弧の後のs はカウントされません。


ホームページで回答があり、ある種の正規表現を使用することを知っていたことがわかりました
クリストファー

@Christopher Eh、これは正規表現をほとんど使用していません(先ほど投稿した他のRetinaの回答とは対照的です...)。
マーティンエンダー

シーシュ。正規表現くらい?
クリストファー

なぜこれが機能しないのですか?
リーキー修道女

ので@LeakyNun (?!(2))だけです(?!2)。おそらく(?(2)(?!))またはを意味し(?2)!)ます。また、脱出するの]を忘れて、最終的に+する必要があります*
マーティンエンダー

2

PHP、116バイト

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

オンライン版


PHPを開始する必要はありません<?phpか?
パベル

@Phoenix:開始タグを必要としないスタンドアロンのPHPインタープリターがあります。それが通常ゴルフに使用されるものです。

@ ais523この場合、PHPはコマンドラインから-Rオプションを使用して実行されます
ヨルグヒュルサーマン

2

Python、76バイト

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

Adnan(およびおそらく他の人)が見つけた多くの人が使用するopen vs closeトリックのフラグとして、序数の2番目のLSBを使用する再帰関数。-1オープンと1クローズの累積合計がゼロに達すると、テールがヒットします。インデックスを使用するよりもバイト数が少ないためlen(r)、インデックスは変数に保持されます。インデックスは1から始まります。

オンラインでお試しください!


2

ルビー、35 34バイト

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

DadaのPerl5回答に基づいています。出力は1から始まります。-nオプション(暗黙while getsループ)を指定してRubyインタープリターを呼び出す必要があります。

編集:これも35 34バイトですが、この答えをさらに減らすための別の可能な出発点です。

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

Edit2:後に不要なスペースを削除しましたp

編集3:さらに34バイトの答え。

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

2
PPCGへようこそ!
パベル

1
とても有難い!:)
レイ・ハメル


1

バッチ、172バイト

@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インデックス。<>sはもちろんBatchの特殊文字であるため、全体を引用する必要があるだけでなく、gotoラベルにするなどのトリックすらできません。


1

R、126バイト

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バイト

オンラインで試す

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;}

出力

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

コメント、ダウンボーター。
Khaled.K

私はダウンボーターではありませんでしたが、すでにかなり短いCの提出があったことは役に立たないと思います。
Ørjanヨハンセン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.