場所にブレースが存在する場合にブレースをスペースで置き換えるプログラムを書く


17

あなたはプロジェクトマネージャーです。ある日、あなたのプログラマーの一つは非常識(行きませんあなたのせいに)とコードベース内のすべての式を取って、自分の無能(約わめき散らす、その場で終了する前に、それらにランダムブラケットを追加してもいないあなたのせい)。これは簡単な修正ですが、何らかの理由でリビジョン管理を使用していません(完全にあなたのせいではありません)。そして、何らかの理由で、他のプログラマーは誰も、不一致のブラケットを修正するためにすべての式を調べることを望みませんところで、それはあなたのせいではありません)。最近のプログラマーは、自分で考えています。あなたは自分でそれをしなければなりません。ホラー!そのようなタスクはあなたの下にあるはずでした...

入力は単一の行になり、左角かっこ(( [ {)と右角かっこ()がいくつか含まれます) ] }。また、常にではありませんが、コメント(/* */)および文字列リテラル(" "または' ')およびさまざまな数字、文字、または記号を含む場合があります。

対応する反対(コメントまたは文字列リテラルの外側)を持たない少なくとも1つのブラケット(コメントまたは文字列リテラルの外側)があります。たとえば}{事前のないエラー。別の例:後の(ものがないa )。プログラムは、ブラケットを一致させるために必要な最小数のブラケットをスペースに置き換えます。

例:

(4 + (2 + 3))]==> (4 + (2 + 3)) (端における角括弧)
][][[]]==> [][[]](開始時角括弧)
("Hel(o!"))==> ("Hel(o!") (端における括弧)
( /* )]*/==> /* )]*/ (開始時括弧)
{()]==> () (中括弧と角括弧)

  • 入力は、最も便利な方法(STDIN、コマンドライン引数、ファイルからの読み取りなど)から取得できます。
  • 同じ数の削除で不一致を解決する方法が複数ある場合は、どちらでもかまいません。
  • 括弧内の不一致のみがあります。文字列リテラルとコメントは常に正しく形成されます。
  • タイトルはこのSOスレッドから来ています
  • コメントに引用符、引用符に引用符、コメントにコメント、引用符にコメントが含まれることはありません。

これはコードゴルフであるため、最小バイト数が優先されます。仕様が明確でない場合は、コメントで質問してください。


おっと、編集が衝突しました。:Pすべてを修正する必要があります。
ドアノブ

@Doorknobところで、ありがとう。スペースを拭くからSEを停止する方法を知りませんでした。
アブサン

文字列リテラルでエスケープするものを処理する必要がありますか(例: ("foo (\") bar"))ますか?
ドアノブ

1
私が主張したいことのために正しい出力{{(})であるべき{ } 開口部のシナリオは、コードがそもそも働いていたことを意味し、以降、または同等の{(})私が知っているすべてのプログラミング言語の不一致括弧としてカウント(すなわち「原因うっ滞」??)。しかし、その後、私はすでに答えを書いたので、私は偏見があります。
DLosc 14

3
そうですか。私は十分に無能ではないと思います。;)
DLosc

回答:


6

ルビー、223文字

これは少し長いことが判明しました。

u,b,i=[],[[],[],[]],-1
s=gets.gsub(/(\/\*|"|').*?(\*\/|"|')|~/){|m|u+=[m];?~}
s.chars{|c|i+=1
(t='{[('.index(c))?b[t].push(i):((t='}])'.index(c))&&(b[t].pop||s[i]=' '))}
b.flatten.map{|l|s[l]=' '}
puts s.gsub(/~/){u.shift}

最初に文字列とコメントを削除するので、カウントされません(後で元に戻します)。

次に、文字列を1文字ずつ調べます。開始ブレースが見つかると、その位置を保存します。閉じブレースが見つかると、それぞれの開いているブレースストレージアレイからポップします。

pop戻る場合nil(つまり、開始中括弧が十分になかった場合)、終了中括弧を削除します。このすべてが完了した後、残りの余分な開始ブレースが削除されます(つまり、終了ブレースが十分ではありませんでした)。

プログラムの最後に、すべての文字列とコメントを戻して出力します。

ゴルフをしていない:

in_str = gets

# grab strings and comments before doing the replacements
i, unparsed = 0, []
in_str.gsub!(/(\/\*|"|').*?(\*\/|"|')|\d/){|match| unparsed.push match; i += 1 }

# replaces with spaces the braces in cases where braces in places cause stasis
brace_locations = [[], [], []]
in_str.each_char.with_index do |chr, idx|
    if brace_type = '{[('.index(chr)
        brace_locations[brace_type].push idx
    elsif brace_type = '}])'.index(chr)
        if brace_locations[brace_type].length == 0
            in_str[idx] = ' '
        else
            brace_locations[brace_type].pop
        end
    end
end
brace_locations.flatten.each{|brace_location| in_str[brace_location] = ' ' }

# put the strings and comments back and print
in_str.gsub!(/\d+/){|num| unparsed[num.to_i - 1] }
puts in_str

これは非常に印象的です。しかし、1つの質問:次のような入力でも機能し(("string"/*comment*/)"string"ますか?私が正しく読んでいる場合(未使用バージョン)、文字列とコメントをunparsed配列内のインデックスに置き換えます。これにより((12)3、存在しないインデックス12(または11)のような置換が行われます。ゴルフバージョンではを使用するだけshiftですが、同様の問題がまだないのでしょうか?
DLosc 14

4

Python 3、410 322 317

import re;a='([{';z=')]}';q=[re.findall('".*?"|/\*.*?\*/|.',input())]
while q:
 t=q.pop(0);s=[];i=0
 for x in t:
  if x in a:s+=[x]
  try:x in z and 1/(a[z.find(x)]==s.pop())
  except:s=0;break
 if[]==s:print(''.join(t));break
 while 1:
  try:
   while t[i]not in a+z:i+=1
  except:break
  u=t[:];u[i]=' ';q+=[u];i+=1

括弧のバランスが取れているものが見つかるまで、より小さいものから始めて、可能なすべての削除のセットを試行します。(これにより、私は完全に正しくバランス意味:{{(})生成します( )、ではありません{(})。)

最初のバージョンは再帰的なジェネレーター関数を使用しました。このバージョンは、キューを使用して単純な幅優先検索を実行します。(はい、それは階乗時間アルゴリズムです。問題は何ですか?:^ D)


これは実際に最小の削除を見つけ、正しくネストされた式を生成するため、これが好きですが、@ vonilyaによる最後のコメントは、正しいネストは重要ではないことを示唆しています。しかし、多くのブレースを削除する必要がある場合、それは本当に遅いです。
リチ14

2

C-406

正規表現を使用しないCでの試み。

#define A if((d==125||d==93||d==41)
char*s;t[256];f(i,m,n,p){while(s[i]!=0){int c=s[i],k=s[i+1],v=1,d;if((c==42&&k==47)||(c==m&&i>n))return i;if(!p||p==2){if((c==39||c==34)||(c==47&&k==42)){i=f(i,c*(c!=47),i,p+1);
c=c==47?42:c;}d=c+1+1*(c>50);A){v=f(i+1,d,i,2);if(!p&&v)t[d]++;if(p==2&&v)i=v;}}d=c;A&&!p){v=!!t[c];t[c]-=v;}if(p<2)putchar(c*!!v+32*!v);i++;}return 0;}main(int c,char*v[]){s=v[1];f(0,0,0,0);}

コンパイルして実行するには(Linuxマシンで):
gcc -o
brackets brackets.c ./brackets "[(])"

[(])のような未定義の場合、最後の有効なブラケットペア()を返します。


2

Python 3、320

import re
O=dict(zip('([{',')]}'))
def o(s,r,m=0,t=[]):m+=re.match(r'([^][)({}/"]|/(?!\*)|/\*.*?\*/|".*?")*',s[m:]).end();return r and o(s[:m]+' '+s[m+1:],r-1,m+1,t)or(o(s,r,m+1,t+[O[s[m]]])if s[m]in O else[s[m]]==t[-1:]and o(s,r,m+1,t[:-1]))if s[m:]else not t and s
s=input();i=0;a=0
while not a:a=o(s,i);i+=1
print(a)

DLoscのソリューションと同様に、これは可能なすべての削除を調査しますが、より高速な再帰的探索およびフォールバック戦略を使用します。コードゴルフでは速度は基準ではなく、徹底的な検索は指数関数的であることがわかっていますが、これ({({({({({({({({(}}}}}}}}は数秒で入力を処理できます。


よくやった、よくやった。私はなんとか317に達することができましたが、かなり簡単に合格できるはずです。(その間、私のプログラムはまだあなたの入力例で
かき回してい

@DLosc:息を止めないでください:)。私のマシンは、6つの開いた丸印でそのパターンのバージョンを実行するのに58分かかりました。宇宙が熱死に達する前に停滞を解決するには、キューをメモする必要があります。そうしないと、最終的なO(n!!)解決策になりO(n!)ます。(私のゴルフは、O(n*2^n)代わりにO(2^n)o実際rに正確に除去ではなく、除去までのすべてのパターンを生成するためrです。簡単に修正できますが、数文字のコストがかかります。)
rici 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.