文字列の非親子化


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/8478およびmeta.codegolf.stackexchange.com/questions/2447/…を参照してください。
マーティンエンダー

2
@redstonerodent私がよく使う言い回しは、「STDIN(または最も近い代替)、コマンドライン引数または関数引数を介して入力を取り、STDOUT(または最も近い代替)、関数の戻り値を介して結果を出力するプログラムまたは関数を記述できますまたは関数(出力)パラメーター。」そして、あなたの場合、「出力は、便利で、明確な、フラットリスト形式であるかもしれません。」
マーティンエンダー

回答:


11

JavaScript ES6、91 93 104133 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を再帰)正規表現であり、2番目のグループは括弧内のすべてを含む(括弧自体を含まない)および3番目のグループは含む括弧の後のすべて(文字列の最後まで)。

replace(v,r"...",s"\g<3> \g<2>")次に、関連する括弧を削除して、2番目のグループを文字列の末尾(区切り文字として機能するためにスペースの後)に移動します。v == wまで反復することにより、括弧がなくなるまで置換が繰り返されることが保証されます。一致は最後に移動され、次の一致が最初の括弧に行くため、結果は深さの順に分解された文字列になります。

次にsplit、文字列のすべての非空白コンポーネントを、文字列の配列の形式(空白を含まない)で返します。

w=""は、whileループが少なくとも1回実行されるようにするために、もちろん、入力された文字列が空の場合を除いて、ゴルフの形式では必要ないことに注意してください。

3バイトの節約を支援してくれたMartinBüttnerに感謝します。


きちんと、私はRetinaで独立して同じソリューションに到達しました。そこには44バイトありますが、現状ではフルプログラムソリューションは許可されていません。:/
マーティンエンダー

\w代わりにを使用すると、3バイトを節約できます[^()]
マーティンエンダー

@MartinBüttner-ありがとう。私は実際にそれを考えましたが、私は何かを見落としていて、それがいくつかのエッジケースで失敗することを心配していました。しかし、それでいいと言ったら、それでいいです。
グレン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フラグを指定して実行します。最後の行の最後のスペースに注意してください。

私はグレン・オーとは独立してこのソリューションを思いつきましたが、まったく同じであることがわかりました。アイデアは、括弧の最初のペアを照合し、削除し、その内容を出力の最後に(繰り返し)挿入することです。.NETには正規表現の再帰がないため、4バイト長いバランスグループを使用する必要がありました。

最初の正規表現がわからない場合は、グループのバランスに関するSOの回答を参照してください。入力は正しく括弧であることが保証されているため)、の.代わりにと一致させることで2バイトを節約できます\)。次に、残りの文字列とを単に一致させます(.*)$4 $1最初に上記の文字列の残りを書き戻し(括弧とその内容の両方を省略)、次に括弧の内容をスペースの後に書き戻します。+`文字列が(すべての括弧が削除された後にのみ発生する)変化しなくなるまで、この手順を繰り返して網膜に指示します。

空のカッコは2つの連続したスペースになるため、最後に文字列全体をスペースでS`分割します(分割モードを有効にし、正規表現は単一のスペースです)。この_オプションは、Retinaに分割の空の部分を省略するように指示するため、出力に空の結果を含めません。


3

Common 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))))

大文字小文字の変換が不要な場合、これは4バイト少なくなります。入力文字列の両側に左括弧と右括弧を追加し、それをリストとして扱い、リストの最上位要素を文字列に書き込んでから、サブリストを同じ方法で処理するという考え方です。


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は再帰的正規表現のようなものをサポートしていないため、手作業が必要です。式は複数の行に分割され、それぞれがネストの深さのレベルを表します。同じ深さの(したがって同じ行の)個々の式は、で区切られます_。スクリプトは、一度に1つのブラケットで入力文字列を処理します。残りの入力は常に、現在のネストレベルに対応する行の最後に保持されます。


0

Python、161バイト

ここに私が思いついたのは、1行の機能的な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のソリューションなど)ははるかに高速です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.