联锁支架


30

编写一个程序或函数,该程序需要一个八个字节的字符串,其中包含()[]{}<>以任何方式排列的每个字符之一,从而使四个相应的括号类型匹配。例如,]<([){}>输入无效,因为方括号不匹配(尽管所有其他方括号都匹配)。

打印或返回从0到的整数,该整数6表示四种括号类型的六种可能的配对中有多少对是互锁的。如果一种类型的支架恰好出现在另一种类型的支架之间,则认为支架类型对是互锁的。所以([)][(])互锁但是()[][]()([]),和[()]不是。

以字节为单位的最短代码获胜。

输入/输出示例

()[]{}<> : 0
([{<>}]) : 0
<>{[]}() : 0
{<>([])} : 0
<(>)[{}] : 1
<[({)}]> : 1
[{<}]>() : 2
{<>([}]) : 2
<{(>})[] : 3
[(]<){>} : 3
<([>{)}] : 4
(<{[>})] : 4
(<[{)>}] : 5
<{[(>})] : 5
[{<(]}>) : 6
(<{[)>}] : 6

Answers:


17

18岁的CJam

l7~f&_f{\/~;&}s,2/

感谢isaacg提供的一些高尔夫创意:)
在线尝试尝试所有示例

说明:

l         read a line of input
7~f&      clear the lowest 3 bits of each character
           the goal is to convert brackets of the same type to the same char
_         duplicate the resulting string, let's call it S
f{…}      for each character in S, and S (the char and S are pushed every time)
  \       swap the character with S
  /       split S around that character, resulting in 3 pieces:
           before, between, after
  ~       dump the pieces on the stack
  ;       pop the last piece
  &       intersect the first 2 pieces
          after the loop, we have an array of strings
          containing the chars interlocking to the left with each char of S
s         join all the string into one string
,         get the string length
2/        divide by 2, because S has duplicated characters

1
哦,所以你是创建CJam的人?您欠我所有我被CJam答案打败的答案所欠!;)
kirbyfan64sos

6
@ kirbyfan64sos很好,如果您想赢,最好也开始学习它:)
aditsu

9
7~f&?我已经很喜欢这个答案,而我还没有读完其余的答案。
丹尼斯

11

Python 2,163字节

def f(b,e='([{<)]}>',q=range(4)):
 b=[b[b.index(e[j])+1:b.index(e[j+4])]for j in q]
 print sum(sum(abs(b[k].count(e[j])-b[k].count(e[j+4]))for j in q)for k in q)/2

这将检查每对匹配的括号之间的内容,并计算当前出现的单个左括号或右括号的数量。这些之和除以二就是输出。

我敢肯定,比我更好的高尔夫球手会打出更多高尔夫。


31
好吧,它发生了。卡尔文发布了答案。末日在我们身上。
Alex A.

4

GNU sed -r,147

根据此meta-answer,输出为一

y/([{</)]}>/
s/.*/\t& & & & /
:b
y/)]}>/]}>)/
s/\S*>(\S*)>\S* /\1\t/
t
s/\S* //
:
s/(\t\S*)(\S)(\S*)\2(\S*\t)/\1\3\4/
t
s/\S *$/&/
tb
s/\s//g
s/../1/g

注意:\t用实际tab字符替换以获得正确的分数。但是,该程序将与GNU sed兼容。

在线尝试


3

Perl,77个字节

76码+ 1个开关

perl -pe 'y/)]}>/([{</;for$x(/./g){$h{$x="\\$x"}++&&s!$x(.*)$x!$z+=length$1,$1!e}$_=$z'

从STDIN获取输入,并且必须为每个输入重新启动程序。

说明

  1. 将所有封闭式支架都用其对应的开放式支架(y/.../.../)代替。
  2. 然后,对于输入字符串(for$x...)中的每个字符,为该字符()增加一个计数器$h{$x}++
  3. 如果这是我们第二次看到该字符,请获取两次出现之间的距离(length $1),然后从字符串中删除该字符的两次出现。例如,如果字符串是([{([{<<,有两个字符[,并{在两者之间(秒。(处理完s 后,字符串变为[{[{<<,我们将2个数字添加到$z互锁括号的总数()中。
  4. 结果取自$z$_=$z

3

Pyth,20个字节

JmC/CdTzlsm@FPcsJd{J

测试套件

JmC/CdTz:首先,这通过将每个输入字符映射到其字符代码(Cd)除以10(/ T)来将每个符号对转换为单个字符,这对每一对都是相同的,但在所有对之间是不同的。结果数字将转换回一个字符,以便以后显示(C)。结果字符列表保存到J

lsm@FPcsJd{J:现在,我们映射J{J)中的唯一字符。我们首先将J使用当前字符作为分隔符(csJd)进行级联而形成的字符串切碎。如果一对括号出现在第二对和第一或第三组中,则该括号与当前对重叠。为了避免重复计算,我们只计算第一组和第二组的情况。因此,我们删除了第三组(P)并取了其余组(@F)的交集。最后,我们将重叠字符(s)串联起来,并打印resut(l)的长度。


3

Python 3、107

t=0
s=""
for x in input():s+=chr(ord(x)&~7)
for x in s:a=s.split(x);t+=len(set(a[0])&set(a[1]))
print(t//2)

松散地基于我的CJam解决方案。


3

视网膜128个 108 64 62 55字节

(T`)]>}`([<{
(\D)(.*)\1(.*)
\n$2\n$3
(?=(\D).*\n.*\1)
1
\n
<empty>

其中<empty>代表空的尾随线。为了进行计数,请将每行放在一个单独的文件中,并\n用实际的换行符替换。为了方便起见,您可以将此等效代码与-s单个文件中的标志一起使用:

(T`)]>}`([<{
(\D)(.*)\1(.*)
#$2#$3
(?=(\D)[^#]*#[^#]*\1)
1
#
<empty>

输出是一元的

说明

第一个命令(告诉Retina循环执行整个代码,直到迭代停止更改字符串为止。在这种情况下,它将总是重复四次,每种括号类型一次。

T`)]>}`([<{

这只是将每个结束括号变成相应的开始括号,以便稍后我们可以使用简单的反向引用将相应的括号匹配。(此阶段在第一次迭代后变为空操作。它仅包含在循环中,因为T已经需要反引号,因此(仅增加成本一个字节,而不是两个字节。)

(\D)(.*)\1(.*)
\n$2\n$3

这将用换行符替换最左边的括号。我们使用\D方括号与1后面在循环中添加的s 进行区分。的(.*)在只有一个对将被替换的末端确保(因为比赛不能重叠)。

(?=(\D).*\n.*\1)
1

整个正则表达式处于前瞻状态,因此它与position匹配。更具体地说,它与每对括号中的一个位置匹配,该位置已被我们刚刚变成换行符的其他括号分隔开。将A 1插入每个位置。我们可以只将1s 保留在那里,因为它们不会影响其他任何正则表达式(因为\Ds确保我们不会意外地匹配它们)。

\n
<empty>

最后,我们删除换行符(即,当前括号类型的占位符)-这意味着我们已将剩下的问题简化为长度为6的字符串,只包含3种类型的括号,但否则工作原理完全相同。

最后,只剩下1我们插入的s,它们的数量与互锁支架的数量完全对应。


2

的JavaScript(ES7),121个 117字节

x=>(a=b=0,[for(c of x)for(d of'1234')(e=c.charCodeAt()/26|0)==d?a^=1<<d:b^=(a>>d&1)<<d*4+e],f=y=>y&&y%2+f(y>>1))(b)/2

哇。那很有趣。当这个挑战第一次出现时,我勾勒出一个答案的想法,但是它的长度超过150个字节,我不想花很多精力去打高尔夫球。昨天我在笔记本上遇到了这个想法,并决定在我完全打高尔夫球之前不要停止思考。我最终写出了两种全新的算法,其中第一种在用大量比特攻击击中约25个字节后,缩短了几个字节。

怎么运行的

首先,我们设置变量a,并b0a是我们当前位于其中的括号对的4位二进制数组,并且b是其中括号对链接在一起的16位二进制数组。

接下来,通过每一个字符,我们可以循环cx,并且每个字符d'0123'。首先,我们确定支架的类型是什么ce=c.charCodeAt()/26-1|0。每种括号类型的十进制字符代码如下:

() => 40,41
<> => 60,62
[] => 91,93
{} => 123,125

通过除以26,减去1和下限,我们将它们分别映射到0、1、2和3。

接下来,我们检查此数字是否等于的当前值d。如果是,我们要么进入或离开d第托架的类型,所以我们翻转d在第i比特aa^=1<<d。如果不是的话,但我们里面d次支架类型,我们需要翻转e个位的d的第4位的部分b。这样做是这样的:

b^=(a>>d&1)<<d*4+e

(a>>d&1)返回中的d第th位a。如果我们在d第一个方括号内,则返回1;否则,返回0。否则,它返回0。接下来,我们将其向左移d*4+e一位b,对结果进行XOR 。如果我们在d第一个括号类型内,则将X的d*4+e第X 位与XOR进行异或b。否则,它什么都不做。

在所有循环结束时,b将包含等于期望返回值两倍的1位数字。但是我们仍然需要弄清楚这是多少位。这就是子功能的所在f

f=y=>y&&y%2+f(y>>1)

如果y为0,则简单地返回0。否则,它y使用with 的最后一位y%2,然后y通过该函数再次添加除最后一位以外的所有内容。例如:

f(y)         => y && y%2 + f(y>>1)
f(0b1001101) =>       1  + f(0b100110) = 4
f(0b100110)  =>       0  + f(0b10011)  = 3
f(0b10011)   =>       1  + f(0b1001)   = 3
f(0b1001)    =>       1  + f(0b100)    = 2
f(0b100)     =>       0  + f(0b10)     = 1
f(0b10)      =>       0  + f(0b1)      = 1
f(0b1)       =>       1  + f(0b0)      = 1
f(0b0)       => 0                      = 0

我们运行b此函数并将结果除以2,我们得到了答案。


1

Oracle SQL 11.2,206字节

WITH v AS(SELECT b,MIN(p)i,MAX(p)a FROM(SELECT SUBSTR(TRANSLATE(:1,'])>}','[(<{'),LEVEL,1)b,LEVEL p FROM DUAL CONNECT BY LEVEL<9)GROUP BY b)SELECT COUNT(*)FROM v x,v y WHERE x.i<y.i AND x.a<y.a AND y.i<x.a;

未打高尔夫球:

WITH v AS( -- Compute min and max pos for each bracket type
           SELECT b,MIN(p)i,MAX(p)a 
           FROM   ( -- replace ending brackets by opening brakets and split the string  
                    SELECT SUBSTR(TRANSLATE(:1,'])>}','[(<{'),LEVEL,1)b,LEVEL p 
                    FROM DUAL 
                    CONNECT BY LEVEL<9
                  )
           GROUP BY b
         )
SELECT COUNT(*)
FROM   v x,v y
WHERE  x.i<y.i AND x.a<y.a AND y.i<x.a -- Apply restrictions for interlocking brackets  
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.