長さnのすべてのブレース文字列を生成する


16

*()[]中括弧は、中括弧が正しく一致する文字で構成される文字列として定義されます。

[brace-string] ::= [unit] || [unit] [brace-string]
[unit]         ::= "" || "*" || "(" [brace-string] ")" || "[" [brace-string] "]"

これは有効なブレース文字列です。

((())***[]**)****[(())*]*

しかし、これらはそうではありません:

)(
**(**[*](**)
**([*)]**

あなたの仕事は、正の整数を与えられ、n入力として数値を取り、長さのすべての有効な中括弧文字列を出力する(または返す)プログラム(または関数)を書くことですn

仕様書

  • 文字列は任意の順序で出力できます。
  • リストまたは異なる文字で区切られた文字列として出力できます。
  • プログラムは0を正しく処理する必要があります。長さ0のブレース文字列が1つありますが、これは空の文字列""です。
  • これはであるため、バイト単位で測定された最短の有効な回答が勝ちます。

テストケース

0. 
1. *
2. ** () []
3. *** ()* []* (*) [*] *() *[]
4. **** ()** []** (*)* [*]* (**) **() **[] *(*) *[*] (()) ()() ()[] ([]) [**] [()] [[]] []() [][] *()* *[]*

3
出力内のエントリの数であるA025235
ガブリエルBenamy

@GabrielBenamyああ。私はそれが以前に見られていたかどうか疑問に思っていました。面白い。
エソランジングフルーツ

2
勝利条件は何ですか?最短のプログラム(コードゴルフ)を想定しています。
-Zgarb


1
誰もがこれがコードゴルフであると想定しているため、それに応じて課題にタグを付けます(そうしないと、既存のすべての回答が無意味になります)。別の勝利基準を意図した場合は、新しいチャレンジを投稿することを検討できます。
マーティンエンダー

回答:


3

ゼリー、29バイト

@JonathanAllanのおかげで-3バイト

問題、バグ、エラー、またはノックできるバイトがある場合は警告してください

“[(*)]”ṗµḟ”*œṣ⁾()Fœṣ⁾[]FµÐLÐḟ

オンラインでお試しください!

私が持っていた以前のソリューション:

“[(*)]”ṗµḟ”*œṣ⁾()Fœṣ⁾[]FµÐL€Ṇ€Tị
“[(*)]”ṗµ¹ḟ”*œṣ⁾()Fœṣ⁾[]FµÐL€Ṇ€Tị
“[(*)]”ṗµ¹ḟ”*œṣ⁾()Fœṣ⁾[]FµÐL€Ṇ€×Jḟ0ị
“[(*)]”x⁸ṗ⁸Qµ¹ḟ”*œṣ⁾()Fœṣ⁾[]FµÐL€Ṇ€×Jḟ0ị
“[(*)]”x⁸ṗ⁸Qµ¹µḟ”*œṣ⁾()Fœṣ⁾[]FµÐL€Ṇ€×Jḟ0ị
“[(*)]”x⁸ṗ⁸Qµ¹µḟ”*œṣ⁾()Fœṣ⁾[]FµÐLµ€Ṇ€×Jḟ0ị

説明(説明に対する私の最善の試み):

Input n
“[(*)]”ṗ-All strings composed of "[(*)]" of length n
µḟ”*    -Filter out all occurences of "*"
œṣ⁾()   -Split at all occurences of "()"
F       -Flatten
œṣ⁾[]   -Split at all occurences of "[]"
F       -Flatten
µÐL     -Repeat that operation until it gives a duplicate result
Ðḟ      -Filter

フィルタリングを使用して3バイトを保存できます(“[(*)]”ṗµḟ”*œṣ⁾()Fœṣ⁾[]FµÐLÐḟ
ジョナサンアラン

15

プロローグ、69バイト

s-->[];e,s.
e-->"*";"(",s,")";"[",s,"]".
b(N,A):-length(A,N),s(A,[]).

Prologの最も興味深い特性の1つは、多くの場合、プログラムを逆方向に実行できることです。たとえば、何かが真かどうかをテストする代わりに、真であるすべてのソリューションを生成できます。また、文字列の長さをチェックする代わりに、特定の長さのすべての文字列を生成できます。(Prologのもう1つの優れた特性は、各述語定義の終了後に空白が必要であり、スペースと同じくらい安価に改行を挿入できることです。したがって、ゴルフプログラムでもかなり読みやすいことがよくあります。)

上記は、b文字列が指定された長さを持ち、質問で定義された「中括弧」であるかどうかをテストする述語(関数に相当)を定義します。具体的には、Prologの文法/正規表現/パターンマッチサポートを介してこれを行い、この種の表現を定義するための素敵で短い砂糖を提供します(明らかにこれは標準/移植可能ですが、元々答えを書いている間はこれを知りませんでしたので、答えは1つのProlog実装でのみ機能すると仮定しましたが、標準に準拠するすべての実装で機能するようです)。プログラムは英語にかなり直接翻訳できます。最初の2行には、「sは空の文字列、またはeの後にsが続きます。e3番目の行は、「Aが長さNのリストで、Asの後にnullが続く場合、NbAになる可能性がある」と解釈できます。アスタリスク、括弧内のs、または角括弧内のsです。ストリング。"

私はいくつかの注意を払ってs(したがってb)、それぞれの「ブレース文字列」が正確に1つの方法で一致するようにしました(これが1つの述語にグループ化するのではなく、両方が存在seなければならない理由です)。これにより、両者は完全に可逆になります。したがってb、文字列が指定された長さのブレース文字列であるかどうかのテストに加えて、指定された長さのすべての「ブレース文字列」を生成するために使用できます。文字列ですが、それはほとんど確実に最も有用でない操作モードです)。実装は再帰的です。たとえばsを生成するために、コードは必要な出力の長さ以下のすべての可能なeを生成し、すべての可能なsを追加します残りのスペースに収まるs。引数の長さを事前に(b内で)指定したため、Prologエンジンは、指定された長さよりも長い出力を生成できないことを認識しており、再帰を終了できます。

動作中のプログラムの例を次に示します。

| ?- b(4,A),format("~s ",[A]),fail.
**** **() **[] *()* *(*) *[]* *[*] ()** ()() ()[] (*)* (**) (()) ([]) []** []() [][] [*]* [**] [()] [[]]

プログラムを「前方に」実行するか「後方に」実行するかを指定するために必要な構文にいくらかのコストがあるはずだと感じています。perlはそのようなことのすべてのビットに対して1バイトを支払います
Sparr

さて、最後の引数は常に戻り値になるというルールを作成し、引数の順序を逆にしてプログラムを実行している方向を指定できます。ゴルフ言語では、入力が与えられたかどうかを調べることで、自分が何をすべきかを理解することはかなり一般的であり、これは比較可能な原則です。ただし、一般的に、可能なすべての言語に適用されるルールを作成することは困難です。などの組み込みコマンドで実行lengthし、appendいずれかの方法でラウンドすることは、言語の基本的な部分であり、ユーザの機能は、多くの場合、同じことを行います。

ああ、うーん。あなたの例には、問題の動作を引き起こす何らかの兆候があると思いました。
スパー

いや、それは完全に議論が与えられているためです。上記のプログラムでは、次のように書きlength(A,N)ます。if Nが与えられてAいない場合(プログラムで要求された方法で述部が使用された場合lengthに発生します)、不明な要素でA構成されるリストが生成さNれます。リストの長さlength測定するために使用することは、おそらくより一般的に使用されます(ただし、「後方」に使用することは、Prologプログラミングではかなり一般的です)。ほとんどの述語は、ほとんど同じように機能します(それらが逆にならない場合、無限ループが構築されるため、そうしない唯一の理由はかなり一般的です)。

1
@ ais523 -->およびDCGは一般に標準ISO Prologです。
16年

5

Haskell、101 94バイト

Zgarbによって7バイトが節約されました!

b 0=[""]
b n=[x++y|k<-[1..n],x<-u k,y<-b$n-k]
u 1=["*"]
u n=[a:s++b|s<-b$n-2,a:b<-["()","[]"]]

定義に従ってほぼ単純ですが、""ケースは移動しました。

使用する:

*Main> map b [0..3]
[[""],["*"],["**","()","[]"],["***","*()","*[]","()*","[]*","(*)","[*]"]]
*Main> length $ b 10
21595

(遅いマシンでは、2番目の計算にかかる時間は1秒未満です。)

また、関数の生成について考えている間に思いついた別のアプローチの結果を共有したいと思います。lengthのすべてのブレース文字列を含む文字列のリスト bのリストを定義します。同様に、サイズのすべての原子が含まれます。1つの良い点は、コードが数字を使用していないことです。それは完全にgolfedされていません:とインライン化することができ、そしてそれは確かにいくつかの他のゴルフをする機会をミス。残念ながら、最初のバージョンよりも短くすることはできませんが、計算はさらに高速です。b!!nnu!!nn-1uilength $ b !! 10

b=[""]:b%u
u=["*"]:map i b
i=concatMap(\s->['(':s++")",'[':s++"]"])
(b:c)%f=zipWith(++)[[x++y|x<-b,y<-e]|e<-f]([]:c%f)

2つのバイトを保存b$n-kしてb$n-2。また、最後の行では、を実行a:b<-["()","[]"]して戻ることができますa:s++b
ズガルブ

使用したかったのです["()","[]"]が、コードサイズを改善する方法がわかりませんでした。ありがとう!
クリスチャンシーバーズ

4

Mathematica、116バイト

#<>""&/@Select[Characters@"*([)]"~Tuples~#,(#/."*"->Nothing//.{a___,"(",")",b___}|{a___,"[","]",b___}:>{a,b})=={}&]&

説明

Characters@"*([)]"

文字列の文字を見つけて"*([)]"List {"*", "(", "[", ")", "]"}

... ~Tuples~#

上記のリストのタプルをlengthで見つけますn

(#/."*"->Nothing//.{a___,"(",")",b___}|{a___,"[","]",b___}:>{a,b})=={}&

タプルのバランスが取れているかどうかを調べるための名前のないブール関数:

#/."*"->Nothing

"*"入力のすべてを削除します。

... //.{a___,"(",")",b___}|{a___,"[","]",b___}:>{a,b}

入力が変更されなくなるまで、"("and ")"または"["andのすべての連続するオカレンスを繰り返し削除します"]"

... =={}

結果が空かどうかを確認しますList

Select[ ... , ... ]

Trueブール関数が適用されるときに与えるタプルを見つけます。

#<>""&/@

List文字をStringsに変換します。


2
意外に{x=a___,"(",")",y=b___}|{x,"[","]",y}も、うまくいくようです。
マーティンエンダー

4

Python 2、128バイト

n=input()
for i in range(5**n):
 try:s=','.join('  "00([*])00"  '[i/5**j%5::5]for j in range(n));eval(s);print s[1::4]
 except:1

再帰的な正規表現をねじ込みます– Pythonのパーサーを使用しています!たとえば、*(**[])*ブレース文字列であることを確認するために、次のことを行います。

  1. のような文字列を作成します"*", (0,"*","*", [0,0] ,0) ,"*"。4文字ごとに2文字目が中括弧からの文字であり、残りの文字はこれをPython式にするための接着剤です。

  2. eval それ。

  3. それがエラーをスローしない場合、印刷しますs[1::4](中括弧文字)。

接着剤の文字は私が作る文字列があれば、有効なPythonの式であり、唯一の4つの利回り有効なブレース文字列のうち、毎秒の文字を取った場合そうすることを選択されます。


2

PHP、149バイト

for(;$argv[1]--;$l=$c,$c=[])foreach($l?:['']as$s)for($n=5;$n--;)$c[]=$s.'*()[]'[$n];echo join(' ',preg_grep('/^((\*|\[(?1)]|\((?1)\))(?1)?|)$/',$l));

古き良き世代を使用して、可能な限りすべてを生成してから、メソッドをフィルタリングします。次のように使用します:

php -r "for(;$argv[1]--;$l=$c,$c=[])foreach($l?:['']as$s)for($n=5;$n--;)$c[]=$s.'*()[]'[$n];echo join(' ',preg_grep('/^((\*|\[(?1)]|\((?1)\))(?1)?|)$/',$l));" 4

1

Python、134バイト

from itertools import*
lambda n:[x for x in map(''.join,product('*()[]',repeat=n))if''==eval("x"+".replace('%s','')"*3%('*',(),[])*n)]

repl.it

長さの有効な文字列のリストを返す名前のない関数n
フォームのすべての長さnの文字のタプルは*()[]、使用して文字列にそれらを結合しmap(''.join,...)、「ペア」を除去することにより、バランスの取れたブラケットを持っているもののため、フィルター"*""()"および"[]"ターンでn結果は空の文字列であることを時間とチェック(n時間は特にために、過剰です"*"が、ゴルファーです)。


1

網膜、78バイト

バイトカウントはISO 8859-1エンコードを前提としています。

.+
$*
+%1`1
*$'¶$`($'¶$`)$'¶$`[$'¶$`]
%(`^
$';
)+`(\[]|\(\)|\*)(?=.*;)|^;

A`;

オンラインでお試しください!

説明

長さ5のすべての可能な文字列を生成し、無効な文字列を除外します。

.+
$*

これ1は、数字として使用して、入力を単項に変換します。

+%1`1
*$'¶$`($'¶$`)$'¶$`[$'¶$`]

これは、各行の+最初の(1)を繰り返し()置き換え、%可能な文字ごとに1つの行の5つのコピーを作成するように置き換えます。これは、接頭辞と接尾辞置換を使用して行われ、 $`そして$'各ラインの残りを構築します。

このループは、置き換える1がなくなると停止します。この時点でN、各行に1つずつ、長さの可能なすべての文字列があります。

%(`^
$';
)+`(\[]|\(\)|\*)(?=.*;)|^;

これらの2つのステージは、各行に対して個別に実行されます(%)。最初の段階では、単純に行を複製し;、2つのコピーを分離します。

第二段階は、別のループである(+繰り返し除去)[]()または*文字列の最初のコピーから、または(文字列が完全に消滅した後にのみ可能である)行の先頭にセミコロンを除去します。

A`;

有効な文字列は、その前にセミコロンがなくなったものなのでA、セミコロンを含むすべての行()を単純に破棄します。


入力5でonlinyを試しました:わかりました。入力6でエラーページが表示されました
-edc65

@ edc65は私には有効ですが、もちろんこのアプローチは正確には効率的ではないため、数秒かかります。どのようなエラーページを意味しますか?
マーティンエンダー

入力5:3秒で答えます。入力6:7秒後、出力ボックス内で、プロキシからエラーページと思われるHTMLソースを取得します。それは非常に短いタイムアウトですタイムアウトなら、私は私の答えはOK入力5までが、6以上の間違ったようだと...私は、入力6のための右のテストケースを取得しようとしていた
edc65

@ edc65間違いなく7秒より長くかかり、TIOのタイムアウトは1分です。あなたが説明したエラーを見たことがありません。TIO チャットでこれを取り上げる価値があるかもしれません(または、GitterGitHubを好むなら))。参照出力については、ここに入力6で得られるものがあります:pastebin.com/WmmPPmrc(入力7には1分以上かかります。)
Martin Ender

1

Python 3.5、146バイト

import re;from itertools import*;lambda f:{i for i in map(''.join,permutations("[()]*"*f,f))if re.fullmatch("(\**\[\**\]\**|\**\(\**\)\**)*|\**",i)}

他の回答と比較して非常に長いが、私が現在見つけることができる最短のもの。無名ラムダ関数の形式であるため、次の形式で呼び出す必要があります

print(<Function Name>(<Integer>))

入力長のすべての可能な中括弧文字列を表す、順序付けられていない文字列のPython セットを出力します。

たとえば、上記の関数の名前がであると仮定するとG、呼び出しG(3)は次の出力になります。

{'[*]', '*()', '*[]', '(*)', '***', '[]*', '()*'}

オンラインでお試しください!(イデオン)


ただし、私のように、組み込み機能を使用して物事を単純化するのが本当に好きではない場合は、ここに私の独自の答え置換を見つけるために外部ライブラリを使用せ、現在、なんと288 237バイトに立っている次のとおりです:

import re;D=lambda f:f and"for %s in range(%d)"%(chr(64+f),5)+D(f-1)or'';lambda g:[i for i in eval('["".join(('+''.join('"[()]*"['+chr(o)+'],'for o in range(65,65+g))+'))'+D(g)+']')if re.fullmatch("(\**\[\**\]\**|\**\(\**\)\**)*|\**",i)]

繰り返しになりますが、競合する答えのように、これはラムダ関数の形式であるため、次の形式でも呼び出す必要があります。

print(<Function Name>(<Integer>))

入力長のすべてのブレース文字列を表す未ソート文字列のPython リストを出力します。たとえば、ラムダがとして呼び出される場合、今回の出力は次のようになります。G(3)

['*()', '(*)', '*[]', '[*]', '()*', '[]*', '***']

また、これは多くの長さのすべてのブレース-文字列を検索することができるという、より速く私の他の答えよりも11程度で115秒、長さのもの10についてで19秒、長さのもの9についてで4秒の長さのものと、8中私のマシンでは約0.73秒ですが、競合する回答はの入力に対して115秒よりもはるかに長くかかります6

オンラインでお試しください!(イデオン)


0

05AB1E、23バイト

…[(*.∞sãʒ'*м„()„[]‚õ:õQ

これらの機能の一部は、質問の投稿後に実装された可能性があります。どんな提案でも大歓迎です!

オンラインでお試しください!

どうやって?

…[(* - the string '[(*'
.∞ - intersected mirror, '[(*'=>'[(*)]'
s - swap the top two items, which moves the input to the top
ã - cartesian power
ʒ ...  - filter by this code:
  '*м      - remove all occurrences of '*'
  „()„[]‚  - the array ["()","[]"]
  õ        - the empty string ""
  :        - infinite replacement (this repeatedly removes "()", "[]", and "*" from the string
  õQ       - test equality with the empty string

05AB1Eを知りませんが*、削除配列に含めることはできませんか?そして、õQチェックをNOTのようなものに置き換えることができますか?
エソランジングフルーツ

最初の提案では、バイトを保存しません:'*м„()„[]‚õ:vs „()„[]‚'*«õ:(テストなし)、3つの値を連結するコマンドがないためです。2番目の文字列は、文字列AFAIKでそのように動作するNOTがないため機能しません。(知る限りでは「私の知る限り」)
ザカリー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.