İlk Parantez Maçını Bul


22

Bu, Brain-Flak'ın doğum gününe götüren bir dizi zorluktan biriydi. Daha fazlasını burada bulabilirsiniz .

Meydan okuma

Bu zorluk için amacınız, tamamen uyumlu bir ()[]{}<>parantez dizisindeki ilk eşleşen parantez çiftini bulmak olacaktır . DJMcMayhem'in tam olarak eşleşen bir dizge tanımını ödünç almak için :

  • Bu meydan okuma amacıyla bir "parantez" bu karakterlerin herhangi biridir: ()[]{}<>.

  • Açma ve kapama parantezleri doğru sıradaysa ve içlerinde karakterleri yoksa, bir parantez bir çift parantez olarak kabul edilir.

    ()
    []{}
    

    Veya içindeki her alt öğe de eşleşirse.

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

    Alt öğeler ayrıca birkaç kat derinlikte yuvalanabilir.

    [(){<><>[()]}<>()]
    <[{((()))}]>
    
  • Bir dizginin, yalnızca her bir çift dirsek doğru açma ve kapama dirseğine doğru sırada sahip olması durumunda ve "Tamamen eşleşir" olarak kabul edilir.

Giriş

Giriş, yalnızca karakter içeren tek bir boş olmayan dizgiden veya karakter dizisinden oluşacak ()[]{}<>ve tam olarak eşleştirilmesi garanti edilir. Giriş / çıkış varsayılanlarımıza uygun olan herhangi bir makul şekilde giriş yapabilirsiniz .

Çıktı

Programınızın veya fonksiyonunuzun çıktısı, ilkini kapatan braketin indeksi olacaktır. Çıktı ya endekslenmiş ya da indekslenmiş olmalıdır . Yine, çıktı bizim g / Ç varsayılanlarımıza uygun herhangi bir makul şekilde olabilir .01

Test Kılıfları

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

Bu , en az bayt kazanıyor!


3
Brain-Flak ofc :) 'de cevap verirseniz bonus puanlar :)
Outgolfer Erik

1
@EriktheOutgolfer Bitti
DJMcMayhem

1
Bu teknik BF'nin verimsiz uygulamalarını yazmak için çok faydalıdır.
Esolanging Fruit

Yanıtlar:


2

V , 4 bayt

%Dø.

Çevrimiçi deneyin!

Bu, çoğu V yanıtından farklı olarak, 0 indeksleme kullanır. Bu cevaptan ve dilimin ne kadar uzadığıyla gurur duyuyorum. Açıklama:

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

<> İle eşleşmesi için gereken bir kazan plakası yok mu?
Pavel

@Pavel Vim, evet. Ama V. değil
DJMcMayhem

27

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

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

Çevrimiçi deneyin!

136 byte kod, artı bir byte -a. Bir tanesi indekslendi.

530 bayt golf attı! Muhtemelen şimdiye kadar yaptığım en büyük golf.

Riley sayesinde 14 bayt kurtarıldı!

Bu, açma / kapama parantezinin bir formülünü kötüye kullanır: ASCII değerlerini alırsanız, bir artırırsanız ve 4 modulo ({[<alırsanız , açıcılar ( ) her zaman 0veya 1kapanır ( )}]>) her zaman 2 veya 3 olur.

Açıklama:

#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
Tanrı aşkına, bu dünyadaki şey.
Leaky Nun

Temel olarak şimdi herkes, açma / kapama braketlerini ayırmak için n-1&2/ n+1&2/ -n&2veya kullanıyor n%7&2...
ETHproductions

@ETHproductions Beyin flakasının verimli bir şekilde işlem yapıp yapamayacağından emin değilim &2, ancak araştırıyorum .
DJMcMayhem

Oh, sanıyordum. 0/ 1Ve 2/ 3... arasında ayrım yapmak için benzer bir şey yapıyor olmalısın, ama şimdi baktığımda, sadece pozitifse azalıyorsun. Serin bir hile de :-)
ETHproductions

1
Daha (TOS+1)%4kısa olabilir: Çevrimiçi deneyin!
MegaTom

11

05AB1E , 17 16 10 bayt

-1 Carusocomputing sayesinde

-6. Adnan’a verdiği müthiş kavrayış için teşekkürler. “Arttırdıktan sonra ikinci son parçanın bir açılış braketi için 0, bir kapanış braketi için 1

Ç>2&<.pO0k

Çevrimiçi deneyin!

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

žuburada kullanılabilir görünüyor.
Magic Octopus Urn,

žu8ÝÈÏyani, hayır, gerçekten lol değil. En iyi ihtimalle hala 5 bayt olacak. Daha fazla parantez çiftine ayrılmayı düşünüyordum ve sadece bir çift kalana kadar parantezleri çıkardım, çıkarılan her çift için 2'lik artış sayacı. Eğer daha az olsa da hiçbir fikrim yok. Atm deniyorum.
Magic Octopus Urn,

10 için bayt: Ç>2&<.pO0k.
Adnan

1
Sadece ASCII değerleri ile uğraşmak . Artışın ardından ikinci son bitin 0bir açma braketi ve 1bir kapatma braketi için olduğunu unutmayın.
Adnan

11

Vim, 23 bayt

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

Çevrimiçi deneyin!

Bu cevap için gerçekten çok üzgünüm. Bu çözüm güzel ve zarif, ama kısa, varsayılan olarak, vim dikkate almaz <ve >eşleşir, bu yüzden 13 bayt boyler koduna ihtiyacım var. Aksi takdirde, bu sadece 10 bayt olur.

Yani değişen, bir V cevabını yayınlanmıştır olurdu, ama bu sadece bir byte daha kısa olacağını Vretmek Òberi, Vrortak bir vim-deyim olduğunu.

Bu 1-endeksli ama trivially değiştirerek 0 endeksli olacak şekilde modifiye edilebilir 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
Sonra bir V cevabı
gönderin

10

Jöle , 11 10 9 bayt

O’&2’+\i0

Çevrimiçi deneyin!

açıklama

Buradaki fikir, açılışı kapama parantezlerinden ayırabilen bir "sihirli formül" bulmaktı. Başlangıçta kullandım O%7&2(yani "ASCII kodunu al, modulo 7, bitwise ve 2"), ama @ETHproductions önerdi O’&2(ki bu modulo 7'nin bir azalmasıyla değiştirildi); her ikisi de bir çeşit parantez için 0, diğeri için 2 döndürür. 1 ( ) 'in çıkarılması bu sonuçları -1 ve 1 haline getirecektir.

Kodun geri kalanı +\. +\birikimli bir miktar üretir. Bir küme parantezinin doğru bir şekilde eşleştirilmesi durumunda, aynı sayıdaki -1 ve 1'leri içerecektir, yani toplam toplamı 0 olacaktır. O zaman sonuç listesinde ilk 0'ın dizinini döndürmemiz gerekir; Bunu beraber yapabiliriz i0.


Büyüleyici kapanış parantezleri bulmak için benzer bir yaklaşım izledik. Ne yazık ki, yalnızca aşağı bir sürümünü buldum:b*2%7>3
2501

İlginç yaklaşım! Sonunda pratikte golf oynamak için daha uzun bir cevap geliştirdim (pratik için), görevinizdeki ilk düşüş yerine, yeterince ilginç olanı dışında, bunun yerine bir artış oldu. :)
HyperNeutrino

9

Retina , 26 24 bayt

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

Çevrimiçi deneyin!

Sonuç 1 tabanlıdır.

açıklama

Esasen tek (ve çok okunabilir bir ...) regex'e dayanan çok farklı bir Retina çözümü. Bu, dengeleme gruplarını kullanarak dengeli dizeleri eşleştirmek için dün keşfettiğim yeni bir tekniği kullanıyor .

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

Regex'in tüm eşleşmelerini ( M) ve return ( !) öğelerini bulun ^.(?<-1>([[({<])*.)*. Bu regex dizenin ilk karakterini atlar ve daha sonra iç içe geçmiş derinliği takip etmek için dengeleme gruplarını kullanır. Herhangi [({<artış derinliği (grup tarafından bir muhafaza parça 1) ve diğer karakter prensipte (derinlik azalır .derinlik hem de açılış parantez azalmış izin verir, ama regex açgözlülükle eşleşti edildiğinden, backtracker olduğunu girişimi asla ). İşin garibi, çalışan (?<-1>...)grup çevreleyen gruptur 1çünkü dengeleyici bir grubun patlaması grubun sonunda gerçekleşir. Bu, formdaki standart yaklaşım üzerinden iki bayt tasarrufu sağlar((open)|(?<-2>close))*. Maç ilkini kapatan brakette durur, çünkü onu atladık, bu yüzden yığın derinliği için hesaba katılmaz (ve yığın derinliği negatif olamaz).

Bu maçın uzunluğu aradığımız braketin 0-temelli endeksidir.


Bu dizedeki boş eşleşme sayısını saymanız yeterlidir. Boş regex her zaman dizedeki karakterlerden bir kez daha eşleşir, bu bize aradığımız braketin 1-temelli indeksini verir.


Bu harika!
Pavel

Daha kısa yaklaşım : ilk kısmı eşleştirmek yerine dizenin ikinci kısmını silin. İpin uzunluğunu nasıl ölçtüğünüzü beğendim btw!
Leo,

@Leo Bu gerçekten temiz! Bunu ayrı bir cevap olarak gönderebilir :)
Martin Ender

Tamam, dengeli dizeler için bu yeni numara harika: D
Leo

6

Retina , 24 bayt

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


Çevrimiçi deneyin!

Bu Martin Ender'in çözümünden ilham aldı .

açıklama

İlk satır, ana dizginin sonuna kadar giden dengeli bir dize izleyen bir karakterle eşleşen bir regex'tir (bu regex'te dengeleme gruplarının nasıl kullanıldığına dair ayrıntılı bir açıklama için Martin'in cevabına bakınız). Regex'ler soldan sağa doğru eşleşmeler aradığından, bu, en uzun dengeli uygun alt eki bulur;

Aşağıdaki satır boştur, bu nedenle eşleşmeyi boş bir dize ile değiştiririz; bu, şimdi (0 dizine alınmış) istenen sonucu almak için yalnızca kalan karakterleri saymamız gerektiği anlamına gelir.

Son boş satır, dizgideki boş dizgenin eşleşme sayısını sayar; bu, dizgideki karakter sayısından bir tanesidir ve 1 dizine dönüştürülmüş sonuca eşdeğerdir.


Bizim cevapların hem iki bayt kaydeder dün dengeli dizeleri eşleştirmek için yeni bir teknik buldu: tio.run/##K0otycxL/K@q4Z7wX0/D3kbX0E4jOlqj2iZWU0tPU0uFi@v/... (ve muhtemelen bir düzine diğerleri ben de yazdım geçmiş ...)
Martin Ender

5

Perl 5 , 28 bayt

Martin Ender'in Retina cevabını kullanarak .yerine 6 bayt kullanıldı .[>})\]]

27 bayt kod + -pbayrağı.

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

Çevrimiçi deneyin!

Özyinelemeli regex, ne güzel bir buluş.
Regex açılış dirseğini ( [<{([]), ardından tekrarlayan çağrıyı ( ?0), ardından bir kapatma dirseğini ( .) arar . Bunların tümü, açık bir şekilde ( +?) olduğundan, en baştan mümkün olduğu kadar kısa sürede eşleşir. Maçın sonunun endeksi cevaptır ve olduğu gibi içinde bulunabilir $+[0].


4

JavaScript (ES6), 55 53 52 bayt

@Adnan sayesinde 1 bayt kaydedildi

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

Her açılış braketi için mod 4 kodunu alarak bize 0 veya 3 verir; kapanış parantezleri için bize 1 veya 2 verir. Bu nedenle, parantezin karakter kodunu (bitleri ve çıkıntıları 1 çeviren) ihmal ederek ve en az ikinci bit alarak, açılış ve kapanış parantezlerini ayırt edebiliriz; bu n&2,.


Ben yerine düşünüyorum n-1&2, -n&2ayrıca çalışır?
Adnan

@Adnan Hmm, bence haklısın. Teşekkürler!
ETHProductions

4

C, 75 72 56 55 54 45 bayt

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

Çevrimiçi çalıştığını görün .

Çıktının, 0 indeksli yerine 1 indeksli olmasını istiyorsanız, sonuncuyu 0ile değiştirin 1.


4

Python 2.7 + Numpy, 85 79 bayt

Kod golfe ilk girişim:

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

1
Siteye Hoşgeldiniz!
DJMcMayhem

1
Lamdas adını vermek zorunda değilsin, g = 'i kaldırabilirsin
Pavel

4

Brain-Flak , 97 bayt (kod için 96, bayrak için 1)

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

-aBayrakla koş .

Çevrimiçi deneyin!

Açıklama:

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

Sadece işe yarıyor, tamam.


3

Retina , 34 bayt

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

Çevrimiçi deneyin!

Sonuç 0 tabanlıdır.

açıklama

^.
!

İlk karakteri a ile değiştirin !. Bu, aradığımız parantezin eşsiz olmasını sağlar.

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

Parantezleri, köşeli parantezleri ve parantezleri açılı parantezlere dönüştürün. Dize tam olarak eşleşmesi garanti edildiğinden, gerçek türleri hiç umursamıyoruz ve bu, bir sonraki adımda bazı baytları kurtarıyor.

+T`p`!`<!*>

Tekrar tekrar ( +) her karakteri s <!*>ile olan tüm eşleşmelerde değiştirin !. Yani, daha fazla işlenmemiş parantez içermeyen parantez çiftleri ile eşleşir ve onları daha fazla ünlem işareti haline getiririz. Bu, eşsiz kapanış braketi hariç tüm dizeyi ünlem işaretlerine dönüştürür.

\G!

İlk ünlem işareti dışındaki ilk ünlem işaretinin 0-temelli pozisyonuna eşit olan ön ünlem işareti sayısını (yani, eşleştirilmemiş braketin) sayın. \GÇapalar bu sayılmaz yüzden önceki birine her maç !sözü parantez sonra s.


Ana sayfada cevap verdiğini gördüm ve bir çeşit regex kullanacağını biliyordum
Christopher

@Christopher Eh, bu ancak herhangi bir regex kullanmıyor (az önce yayınladığım diğer Retina cevabının aksine).
Martin Ender

Sheesh. Regex çok?
Christopher,

Neden değil bu çalışma?
Leaky Nun

@LeakyNun Çünkü (?!(2))sadece (?!2). Muhtemelen (?(2)(?!))ya da demek istedin (?2)!). Ayrıca kaçmaya unuttum ]ve son +olarak ihtiyaçlarını *.
Martin Ender

2

PHP, 116 Bayt

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

Çevrimiçi sürüm


PHP ile başlamak gerekmez <?phpmi?
Pavel

@Phoenix: Başlangıç ​​etiketi gerektirmeyen bağımsız bir PHP tercümanı var. Normalde golf oynamak için kullanılır.

@ ais523 Bu durumda PHP -R seçeneğiyle komut satırından çalışır
Jörg Hülsermann

2

Python , 76 bayt

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

Sıralı 2. LSB'yi Adnan (ve muhtemelen diğerleri) tarafından bulunan birçok kişi tarafından kullanılan açıka yakın hileye bayrak olarak kullanan özyinelemeli işlev. Kuyruk -1açık ve 1kapalı toplamın toplamı sıfıra ulaştığında vurur . Dizin, kullanımına göre bayt ucuz olduğu için değişkende tutulur len(r), dizin oluşturma 1 tabanlıdır.

Çevrimiçi deneyin!


2

Ruby, 35 34 bayt

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

Dayanarak dedemin Perl5 cevap . Çıktı 1 dizinli. Ruby yorumlayıcısının -nseçenekle çağrılmasını gerektirir (örtülü while getsdöngü).

Düzenleme: Bu da 35 34 bayttır, ancak bu cevabı daha da azaltmak için başka bir olası başlangıç ​​noktasıdır.

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

Düzen2: Sonra gereksiz boşluk kaldırıldı p.

Düzen3: Bir kaç tane daha 34 baytlık cevap.

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

2
PPCG'ye Hoşgeldiniz!
Pavel

1
Çok takdir! :)
Ray Hamel

2

Python 3 , 59 55 50 49 bayt

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

Çıktı 0 dizinli. Braket yönünü belirleme formülü ilk önce @ETHProductions tarafından keşfedildi ve @Adnan tarafından geliştirildi.

Çevrimiçi deneyin!


1

Toplu iş, 172 bayt

@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 endeksli. <>Elbette Batch'taki özel karakterlerdir, bu yüzden sadece baştan sona alıntı yapmak zorunda kalmam değil, aynı zamanda gotoetiket yapma gibi numaralar bile yapamıyorum .


1

R, 126 Bayt

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 bayt

Çevrimiçi dene

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

Çıktı

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

Herhangi bir yorum, downvoter.
Khaled.K

Düşkün olan ben değildim, ancak çok daha kısa bir C gönderimi olduğunu sanmıyorum.
Ørjan Johansen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.