对字符串取消括号


25

给定正确括号化的字符串作为输入,输出匹配括号内(或所有括号外)的所有非空子字符串的列表,并删除嵌套括号。每个子字符串应为完全相同的匹配括号中的字符序列。子串应按深度顺序列出,而相同深度的子串应按它们在字符串中出现的顺序列出。假定输入总是正确地加上括号。

您可以假定输入仅包含小写的ASCII字母和括号。

您的答案应该是一个函数,当给定一个字符串时,它返回一个字符串列表。

例子:

                   'a(b)c(d)e' -> ['ace', 'b', 'd']
                   'a(b(c)d)e' -> ['ae', 'bd', 'c']
                  'a((((b))))' -> ['a', 'b']
                        'a()b' -> ['ab']
                            '' -> []
                           'a' -> ['a']
          '(((a(b)c(d)e)f)g)h' -> ['h', 'g', 'f', 'ace', 'b', 'd']
'ab(c(((d)ef()g)h()(i)j)kl)()' -> ['ab', 'ckl', 'hj', 'efg', 'i', 'd']

最少的字节数获胜。


'i''d'在最后的测试情况下,正确的顺序?
PurkkaKoodari

@ Pietu1998 i嵌套的深度小于d
feersum

@feersum哦,对。
PurkkaKoodari

1
您介意也允许其他标准提交类型,特别是完整程序吗?并非所有的语言都有功能的概念。有关默认共识,请参见meta.codegolf.stackexchange.com/a/2422/8478meta.codegolf.stackexchange.com/questions/2447/…
马丁·恩德

2
@redstonerodent我倾向于使用的措辞是“您可以编写程序或函数,通过STDIN(或最接近的替代方案)获取输入,命令行自变量或函数自变量,并通过STDOUT(或最接近的替代方案)输出结果,函数返回值或功能(输出)参数。” 而您的情况是“输出可以采用任何方便,明确,平坦的列表格式。”
马丁·恩德

Answers:


11

JavaScript ES6,91 93 104 133 148

Edit2 2个字节已保存thx user81655

使用更多的字符串和更少的数组进行编辑

在符合EcmaScript 6的浏览器中测试运行以下代码段

f=s=>[...s].map(c=>l+=c<')'||-(o[l]=(o[l]||'')+c,c<'a'),o=[],l=0)&&(o+'').match(/\w+/g)||[]

// Less golfed

u=s=>{
  o=[]; l=0;
  [...s].map(c=>{
    if (c>'(') // letters or close bracket
      o[l]=(o[l]||'')+c, // add letter or close bracket to current level string
      l-=c<'a' // if close bracket, decrement level
    else
      ++l // open bracket, increment level
  })
  o = o+'' // collapse array to comma separated string
  return o.match(/\w+/g)||[] // fetch non empty strings into an array
}

// TEST
console.log=x=>O.innerHTML+=x+'\n'

;[ 'a(b)c(d)e'                    // ['ace', 'b', 'd']
 , 'a(b(c)d)e'                    // ['ae', 'bd', 'c']
 , 'a((((b))))'                   // ['a', 'b']
 , 'a()b'                         // ['ab']
 , ''                             // []
 , 'a'                            // ['a']
 , '(((a(b)c(d)e)f)g)h'           // ['h', 'g', 'f', 'ace', 'b', 'd']
 , 'ab(c(((d)ef()g)h()(i)j)kl)()' // ['ab', 'ckl', 'hj', 'efg', 'i', 'd']
].forEach(t=>console.log(t +" -> " + f(t)))
<pre id=O></pre>


使用保存2个字节c=>l+=c<')'||-(o[l]=(o[l]||'')+c,c<'a'),
user81655

@ user81655好的,谢谢
edc65

8

朱莉娅117 86 83字节

v->(while v!=(v=replace(v,r"(\(((?>\w|(?1))*)\))(.*)",s"\g<3> \g<2>"))end;split(v))

这是一个正则表达式解决方案。

取消高尔夫:

function f(v)
  w=""
  while v!=w
    w=v
    v=replace(v,r"(\(((?>\w|(?1))*)\))(.*)",s"\g<3> \g<2>"))
  end
  split(v)
end

r"(\(((?>\w|(?1))*)\))(.*)"是一个递归((?1)递归组1)正则表达式,它将匹配第一个最外面的平衡括号(不包含不平衡/反向括号),第二组包含括号内的所有内容(不包括括号本身),而第三组包含括号后的所有内容(直到字符串末尾)。

replace(v,r"...",s"\g<3> \g<2>")然后将第二组移到字符串的末尾(在空格后用作定界符),并删除相关的括号。通过迭代直到v == w,可以确保重复替换,直到没有括号为止。因为将匹配项移到末尾,然后下一个匹配项用于第一个括号,结果将是按深度顺序分解的字符串。

然后split以字符串数组的形式(没有空格)返回字符串的所有非空格部分。

请注意,w=""在ungolfed代码中使用,以确保while循环至少运行一次(当然,除非输入字符串为空),并且在golfing形式中不需要。

感谢MartinBüttner为节省3个字节提供的帮助。


整洁,我在Retina中独立地获得了相同的解决方案。它在那里有44个字节,但从目前来看,不允许使用全程序解决方案。:/
Martin Ender

您可以使用\w代替来保存三个字节[^()]
马丁·恩德

@MartinBüttner-谢谢。我实际上已经考虑过,但是我担心自己会忽略某些东西,并且在某些情况下会失败。但是,如果您说很好,那就很好。
Glen O

6

Python,147个字节

def f(s):
 d=0;r=[['']for c in s]
 for c in s:
  if c=='(':d+=1;r[d]+=['']
  elif c==')':d-=1
  else:r[d][-1]+=c
 return[i for i in sum(r,[])if i]

单元测试:

assert f('a(b)c(d)e') == ['ace', 'b', 'd']
assert f('a(b(c)d)e') == ['ae', 'bd', 'c']
assert f('a((((b))))') == ['a', 'b']
assert f('a()b') == ['ab']
assert f('') == []
assert f('a') == ['a']
assert f('(((a(b)c(d)e)f)g)h') == ['h', 'g', 'f', 'ace', 'b', 'd']
assert f('ab(c(((d)ef()g)h()(i)j)kl)()') == ['ab', 'ckl', 'hj', 'efg', 'i', 'd']

我喜欢这个难题;非常可爱!


4

Pyth,32个字节

fTscR)uX0.<GJ-FqLH`()@[Hdk)Jzmkz

测试套件

松散地基于@Quuxplusone的方法。在每个深度处建立空格分隔的字符列表,然后将其拆分并过滤出空组。旋转工作清单以始终保持当前深度的清单在前。


4

视网膜44 41字节

+`\(((\w|(\()|(?<-3>.))*).(.*)
$4 $1
S_` 

-s标志一起运行。注意最后一行的末尾空格。

我独立于Glen O提出了这个解决方案,但事实证明是相同的。想法是匹配第一对括号,将其删除,然后将其内容插入输出的末尾(重复)。由于.NET在正则表达式中缺少递归,因此我不得不使用平衡组,该平衡组长了四个字节。

如果您不了解第一个正则表达式,请允许我参考我关于平衡组的答案。由于可以确保输入正确地)加上括号,因此我们可以通过匹配.而不是来保存两个字节\)。然后,我们只需将字符串的其余部分与匹配(.*)$4 $1首先写回字符串的其余部分(省略括号和括号的内容),然后在空格后括号的内容。该+`告诉视网膜重复此步骤,直到串停止变化(一旦所有的括号被取消了仅发生)。

空括号将导致两个连续的空格,因此最后我们将整个字符串拆分为空格(S`激活拆分模式,而正则表达式为单个空格)。该_选项告诉Retina忽略拆分的空白部分,因此我们不将空白结果包括在输出中。


3

普通Lisp,160

(lambda(x)(labels((g(l)(cons(#1=format()"~(~{~A~}~)"(#2=remove-if'listp l))(mapcan #'g(#2#'atom l)))))(remove""(g(read-from-string(#1#()"(~A)"x))):test'equal))))

如果不需要大小写转换,则可以少四个字节。想法是在输入字符串的每一侧添加左括号和右括号,将其视为列表,将列表的顶级元素写入字符串,然后以相同方式处理子列表。


2

Haskell中,114个 112 111字节

')'%(h:i:t)=("":i):t++[h]
'('%l=last l:init l
c%((h:i):t)=((c:h):i):t
g x=[a|a<-id=<<foldr(%)(x>>[[""]])x,a>""]

用法示例:g "ab(c(((d)ef()g)h()(i)j)kl)()"-> ["ab","ckl","hj","efg","i","d"]

我正在向后浏览输入字符串。中间数据结构是字符串列表的列表。外部列表是按级别[["ab"],["ckl"],["hj"],["efg","i"],["d"]]划分的,内部列表是按级别划分的每个组的,例如(请注意:实际列表之间有很多空字符串)。所有这些都以等于输入长度的空字符串开头-绰绰有余,但是无论如何都会过滤掉空列表。外部列表在(/上旋转)或将字符添加到前元素。)也开始了一个新的小组。

编辑:@Zgarb已找到要保存的字节。


1

Sed,90个字节

:
s/^(\w*)\((.*)\n?(.*)/\1\n\3_\2/M
s/(\n\w*_)(\w*)\)(.*)/\3\1\2/M
t
s/[_\n]+/,/g
s/,$//

使用扩展的正则表达式(-r标志),占+1个字节。另外,它使用GNU扩展(命令M上的标志s)。

用法示例:

$ echo 'ab(c(((d)ef()g)h()(i)j)kl)()' | sed -r -f deparenthesize.sed
ab,ckl,hj,efg,i,d

说明: 由于sed不支持递归正则表达式之类的内容,因此需要手动操作。表达式分为多行,每行代表一个嵌套深度级别。在同一深度(因此在同一行)上的各个表达式用分隔_。该脚本一次遍历输入字符串一个括号。其余输入始终保留在与当前嵌套级别相对应的行的末尾。


0

Python,161字节

这是我想出的一站式功能性python解决方案:

p=lambda s:filter(None,sum([''.join([s[i]for i in range(len(s))if s[:i+1].count('(')-s[:i+1].count(')')==d and s[i]!=')']).split('(')for d in range(len(s))],[]))

这项挑战是受https://github.com/samcoppini/Definition-book启发的,该书输出带有括号中定义的单词的长字符串。我想编写代码,给我每个句子,并删除括号。函数式解决方案太慢而无法在长字符串上有效,但是命令式解决方案(例如@Quuxplusone的解决方案)要快得多。

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.