找到第一场比赛


22

这是Brain-Flak生日前的一系列挑战之一。在这里找到更多。

挑战

对于这一挑战,您的目标是在完全匹配的括号中找到第一对匹配的()[]{}<>括号。借用DJMcMayhem对完全匹配的字符串定义:

  • 出于此挑战的目的,“括号”是以下任意字符:()[]{}<>

  • 如果左括号和右括号的顺序正确且其中没有字符,则将一对括号视为“匹配”

    ()
    []{}
    

    或者,如果其中的每个子元素也都匹配。

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

    子元素也可以嵌套在几层深处。

    [(){<><>[()]}<>()]
    <[{((()))}]>
    
  • 当且仅当每对括号中的正确开/右括号正确且顺序正确时,字符串才被视为“完全匹配”。

输入项

输入将由单个非空字符串或仅包含character的char数组组成()[]{}<>,并保证完全匹配。您可以采用符合我们I / O默认值的任何合理方式进行输入。

输出量

程序或函数的输出将是括号的索引,该括号将关闭第一个括号。输出必须0或已1索引。同样,输出可以以与我们的I / O默认值相对应的任何合理方式进行。

测试用例

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

这是,最少字节获胜!


3
如果您在Brain-Flak ofc中回答,将获得加分:)
独行侠埃里克(Erik the Outgolfer)'17

1
@EriktheOutgolfer 完成
DJMcMayhem

1
该技术对于编写效率低下的BF实现非常有帮助。
硕果累累

Answers:


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中,是的。但不是在五
DJMcMayhem

27

Brain-Flak685、155、151、137字节

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

在线尝试!

136个字节的代码,再加上1个字节-a。一个索引。

击打了530个字节!那可能是我做过的最大的高尔夫球。

感谢赖利节省了14个字节!

这滥用了开/关括号的公式:如果您采用ASCII值,将其递增1,并取4为模,则开环(({[<)将始终为01,而闭环()}]>)将始终为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
为了上帝的爱,这到底是什么。
Leaky Nun

基本上每个人现在都在使用n-1&2/ n+1&2/ -n&2n%7&2区分

我不确定@ETHproductions是否可以有效计算&2,但我将对其进行研究。
DJMcMayhem

哦,我以为你是。您必须做类似的事情来区分0/ 12/ 3...,尽管现在我来看,如果肯定的话,您只是在递减。也是一个很酷的技巧:-)
ETHproductions'Apr

1
(TOS+1)%4可短:网上试试吧!
MegaTom'5

11

05AB1E17 16 10字节

-1感谢carusocomputing

-6感谢Adnan的惊人见解:“递增后,倒数第二个是左括号为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似乎在这里可用。
魔术章鱼缸

žu8ÝÈÏ所以,不,不是真的哈哈。充其量仍然是5个字节。我正在考虑将更多的拆分成几对大括号,然后删除大括号,直到只剩下一对,然后为每个删除的对增加2的计数器。我不知道那是否更少。试用atm。
魔术章鱼缸

对于10个字节:Ç>2&<.pO0k
阿德南

1
只是弄乱 ASCII值。请注意,在递增之后,倒数第二个位0用于左括号和1右括号。
阿德南

11

Vim,23个字节

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

在线尝试!

我对这个答案感到非常难过。该解决方案非常优美且简短,但是,默认情况下,vim不会考虑<>加以匹配,因此我需要13个字节的样板代码。否则,这将只是10个字节。

我会发布一个V答案,但这只会短一个字节,即更改VrÒ,因为这Vr是常见的vim习惯用法。

这是1-索引但是可以平凡修改为通过改变0索引1到一个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答案:)
暴民埃里克(Erik the Outgolfer)'17

10

果冻11 10 9字节

O’&2’+\i0

在线尝试!

说明

这里的想法是找到一个可以区分开括号和闭括号的“魔术公式”。我最初使用O%7&2(即“采用ASCII码,取模7,按位和2”),但是建议O’&2使用@ETHproductions (用减量替换模7)。两者都返回0表示一种括号,返回2表示另一种。减去1()将使结果变成-1和1。

其余代码为+\+\产生累计和。如果一组括号正确匹配,它将包含相同数量的-1和1,即其累加总和为0。然后,我们只需要返回结果列表中前0的索引即可;我们可以用做到这一点i0


让我们着迷的是如何采用类似的方法来检测右括号。不幸的是,我只找到了次等版本:b*2%7>3
2501年

有趣的方法!我提出了一个更长的答案(用于练习),最终我几乎不知所措,除了有趣的是,我没有增加您职位的第一个减数,而是增加了一个薪水。:)
HyperNeutrino'5

9

视网膜26 24字节

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

在线尝试!

结果基于1。

说明

完全不同的Retina解决方案,该解决方案基本上基于单个(且易读...)正则表达式。这使用了我昨天发现的一种新技术,用于使用平衡组匹配平衡的字符串。

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

查找(M)并返回(!)正则表达式的所有匹配项^.(?<-1>([[({<])*.)*。该正则表达式会跳过字符串的第一个字符,然后使用平衡组来跟踪嵌套深度。任何的[({<增加的深度(保持在由组的轨道1),以及任何其他字符减小的深度(在原则上,.允许深度通过开口括号以及被降低,但是由于正则表达式是贪婪地匹配时,backtracker将永远不会尝试该)。怪异的窍门是(?<-1>...)封闭的组1起作用,因为从平衡组弹出的事件发生在该组的末尾。与标准方法相比,此格式节省了两个字节((open)|(?<-2>close))*。比赛一定会停在第一个括号附近,因为我们跳过了它,因此它不在堆栈深度中考虑(堆栈深度不能为负)。

匹配的长度是我们要查找的括号的从0开始的索引。


只需计算此字符串中的空匹配数即可。空的正则表达式总是匹配一次,而不是字符串中有任何字符,因此这为我们提供了要查找的括号的从1开始的索引。


那太好了!
帕维尔

较短的方法:删除字符串的第二部分,而不是匹配第一部分。我喜欢您如何测量字符串的长度,顺便说一句!
狮子座

@Leo真的很整洁!您可以将其发布为单独的答案:)
Martin Ender

好的,这个平衡弦的新技巧很棒:D
Leo

6

视网膜,24字节

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


在线尝试!

这是受到Martin Ender解决方案的启发。

说明

第一行是一个正则表达式,它与一个字符匹配,后跟一个平衡字符串,一直到主字符串的末尾(有关此正则表达式中如何使用平衡组的详细说明,请参见Martin的回答)。由于正则表达式从左到右查找匹配项,因此它将找到最长的平衡适当子前缀,即在关闭第一个括号的括号之后的所有内容,再加上括号本身。

下一行是空的,因此我们将匹配替换为空字符串,这意味着我们现在只需要计算其余字符即可获得(索引为0的)所需结果。

最后一个空行计算字符串中的空字符串的匹配数,该数量比字符串中的字符数多一个,等于1索引的结果。


昨天我发现了一种用于匹配平衡字符串的新技术,该技术在我们的两个答案上都节省了两个字节:tio.run / ## K0otycxL / K @ q4Z7wX0 / D3kbX0E4jOlqj2iZWU0tPU0uFi @ v /…(可能还有我在过去...)
马丁·恩德

5

Perl 5,28个字节

用Martin Ender的Retina answer中的 just .代替保存了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)

对于每个左括号,采用其字符代码mod 4得出0或3;对于右括号,它给出1或2。因此,我们可以通过对括号的字符代码求反(将位翻转并减去1)并取第二个最低有效位来区分开括号和闭括号。即n&2


我认为代替n-1&2-n&2还行吗?
阿德南

@Adnan Hmm,我认为您是对的。谢谢!
ETHproductions

4

C,75 72 56 55 54 45字节

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

看到它在网上工作

如果你想输出为1索引,而不是0索引,替换最后01


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
您不必命名lambdas,可以删除g =
Pavel

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`!`<!*>

重复(+)中的所有匹配替换每个字符<!*>!秒。也就是说,我们匹配不包含其他未处理括号的成对括号,并将它们变成进一步的感叹号。这会将除不匹配的右括号之外的整个字符串变成感叹号。

\G!

计算前导感叹号的数量,该数量等于第一个非感叹号(即不匹配的括号)从0开始的位置。该\G锚每场比赛前一个,这就是为什么这种不计!上述支架后秒。


我在首页上看到您已经回答了,并且知道它将要使用某种正则表达式
Christopher

@Christopher Eh,这个几乎根本不使用任何正则表达式(与我刚刚发布的另一个Retina答案相反)。
Martin Ender

嘘。正则表达式多少?
Christopher

为什么不起作用?
Leaky Nun

@LeakyNun因为(?!(2))(?!2)。您可能是说(?(2)(?!))(?2)!)。您还忘记了逃脱一个],最后一个+需要*
Martin Ender

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选项命令行
约克Hülsermann

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

递归函数,使用序数第二个LSB作为Adnan(甚至可能是其他人)发现的许多技巧使用的打开与关闭技巧的标志。当-1打开和1关闭的累积总和达到零时,将命中尾巴。与使用相比len(r),索引保留在变量中,因为它比字节更便宜,索引基于1。

在线尝试!


2

Ruby,35个 34字节

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

基于Dada的Perl5答案。输出为1索引。要求使用-n选项(隐式)调用Ruby解释器。while gets循环)。

编辑:这也是35 34字节,但这是进一步减少此答案的另一个可能的起点。

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

Edit2:在之后删除了不必要的空格p

Edit3:还有更多的34字节答案。

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

2
欢迎来到PPCG!
帕维尔

1
非常感激!:)
雷·哈默尔

2

Python 3中59个 55 50 49字节

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

输出为0索引。确定括号方向的公式最早由@ETHProductions发现,并由@Adnan改进。

在线尝试!


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当然是批处理中的特殊字符,因此,不仅必须全引号,而且甚至不能做一些使它们成为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提交没有帮助。
与Orjan约翰森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.