Yerlerde parantezlerin durağanlığa neden olduğu durumlarda parantezlerin yerini boşluk alan bir program yazın


17

Siz bir proje yöneticisisiniz. Bir gün, programcılarınızdan biri deliye döndü (hatanız değil ) ve kod tabanındaki tüm ifadeleri aldı ve yerinde ayrılmadan önce, yetersizliğiniz ( hatta hatanız değil) hakkında rastgele parantezler ekledi . Bununla birlikte, bu kolay bir düzeltme olacaktır, ancak bazı nedenlerden dolayı revizyon kontrolü kullanmıyorsunuz ( tamamen hatanız değil ). Ve bir nedenden ötürü, diğer programcıların hiçbiri eşleşmeyen parantezleri düzeltmek için her ifadeden geçmek istemiyor ( bu arada, bu sizin hatanız değil ). Programcıların bu günlerde, kendinize düşünüyorum. Bunu kendiniz yapmanız gerekecek. Korku! Bu tür görevlerin altınızda olması gerekiyordu ...

Giriş, bir dizi sol parantez ( ( [ {) ve sağ parantez ( ) ] }) içeren tek bir satır olacaktır . Ayrıca, her zaman olmasa da, yorumlar ( /* */) ve dize değişmez değerleri ( " "veya ' ') ve çeşitli sayılar, harfler veya simgeler içerebilir .

Karşılıklı bir karşıtlığı olmayan (bir yorumun veya dize değişmezinin dışında) en az bir köşeli ayraç (bir yorumun veya dize değişmezinin dışında) olacaktır. Örneğin, önceliği }olmayan bir errant {. Başka bir örnek: daha sonra (olmayan a ). Programınız, parantezlerin eşleşmesi için gereken minimum sayıda parantez içeren bir boşlukla değiştirilir.

Örnekler:

(4 + (2 + 3))]==> (4 + (2 + 3)) (sondaki köşeli ayraç)
][][[]]==> [][[]](başlangıçtaki köşeli ayraç)
("Hel(o!"))==> ("Hel(o!") (sondaki parantez)
( /* )]*/==> /* )]*/ (başlangıçtaki parantez)
{()]==> () (kıvırcık köşeli ayraç ve köşeli ayraç)

  • Giriş en uygun yoldan alınabilir (STDIN, komut satırı argümanı, bir dosyadan okuma, vb.)
  • Aynı sayıda kaldırma işlemiyle eşleşmeyen sorunu çözmenin birden fazla yolu varsa, her ikisi de kabul edilebilir.
  • Parantez içinde yalnızca uyumsuzluklar olacaktır. Dize değişmez değerleri ve yorumlar her zaman doğru şekilde oluşturulur.
  • Başlık bu SO iş parçacığından geliyor
  • Yorumlarda asla tırnak, tırnak içinde tırnak, yorumlarda yorum veya tırnak içinde yorum olmayacaktır.

Bu kod golf, bu yüzden minimum bayt sayısı kazanır. Spesifikasyon net değilse, yorumlarda soru sorun.


Hata! Düzenlemelerimiz bir tür çarpıştı. : P Şimdi her şey düzeltilmelidir.
Kapı tokmağı

@Doorknob Bu arada bunun için teşekkürler. Boşluk bozulmadan gelen SE durdurmak için nasıl bilmiyordum.
pelin otu

Kaçan şeyleri dizgi değişmezleriyle (ör. ("foo (\") bar")) İşlemek zorunda mıyız ?
Kapı tokmağı

1
Açılış senaryosu, kodun başlamak için çalıştığını ima ettiğinden ve bildiğim her programlama dilinde (yani "durağanlığa neden olur" ??) eşleşmeyen parantez olarak sayıldığından , doğru çıktının veya eşdeğer {{(})olması gerektiğini savunurum. Ama sonra, zaten bir cevap yazdım, bu yüzden önyargılıyım. { } {(})
DLosc

3
Anlıyorum. Sanırım yeterince becerikli değilim. ;)
DLosc

Yanıtlar:


6

Ruby, 223 karakter

Bu biraz uzun oldu.

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}

Yaptığı şey önce dizeleri ve yorumları çıkarmaktır, böylece sayılmazlar (ve daha sonra geri koyarlar).

Sonra, karakter karakter dizeden geçer. Bir açılış ayracı bulduğunda konumunu saklar. Bir kapanış ayracı bulduğunda, ilgili açık ayraç depolama dizisinden çıkar.

Eğer popdöner nil(yani yeterince açıklık ayraçları yoktu), kapanış ayracı kaldırır. Tüm bunlar yapıldıktan sonra, kalan ekstra açma parantezlerini kaldırır (yani yeterli kapanma parantezi yoktu).

Programın sonunda, tüm dizeleri ve yorumları geri koyar ve çıktılar.

Ungolfed:

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

Bu çok etkileyici. Ancak bir soru: yine de böyle bir girdi için çalışacak (("string"/*comment*/)"string"mı? (Okunmamış sürüm) doğru okuyorsanız, dizeleri ve yorumları unparseddizideki dizinleriyle değiştirirsiniz , bu da ((12)3varolmayan bir dizin 12(veya 11) gibi bir ikameye neden olur . Golfçü versiyonun sadece kullandığını görüyorum shift, ama yine de benzer bir problemi olmayabilir mi?
DLosc

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

Diş tellerinin dengeli olduğu yeri bulana kadar daha küçük olanlardan başlayarak olası her silme kümesini dener. (Demek istediğim tamamen doğru dengelenmiş: {{(})üretiyor ( ), değil {(}).)

İlk versiyonda, gerçekten harika ama aynı zamanda uzun olan yinelemeli bir jeneratör işlevi kullanıldı. Bu sürüm, bir kuyruk kullanarak basit bir ilk önce arama yapar. (Evet, faktöriyel bir zaman algoritmasıdır. Sorun nedir?: ^ D)


Bunu beğendim çünkü aslında en az kaldırma buluyor ve doğru iç içe ifadeler üretiyor, ancak @vonilya tarafından yapılan son yorum doğru iç içe yerleştirmenin önemli olmadığını gösteriyor. Ancak, çok sayıda diş telinin çıkarılması gerekiyorsa gerçekten yavaştır.
rici

2

C - 406

Düzenli ifadeler kullanmadan C dilinde bir deneme.

#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);}

Derlemek ve çalıştırmak için (linux makinesinde):
gcc -o parantez parantez.
C ./ braketler "[(])"

[(]) Gibi tanımlanmamış durumlarda son geçerli parantez çiftini () döndürür


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'un çözümü gibi, bu da olası her silme işlemini araştırır, ancak çok daha hızlı olan yinelemeli bir araştırma ve geri dönüş stratejisi kullanır. Hızın kod golfünde bir kriter olmadığını ve kapsamlı aramanın her durumda üstel olduğunu biliyorum, ancak bu ({({({({({({({({(}}}}}}}}birkaç saniye içinde girişleri işleyebilir .


İyi oynadı, iyi oynadı. 317'ye kadar inmeyi başardım, ama bence bunu kolayca geçebilmelisin. (Bu arada, programım hala örnek girişinizde çalkalanıyor ...)
DLosc

@DLosc: Nefesinizi tutmayın :). Makinemin bu modelin versiyonunu 6 açık ebeveyn ile yapmak 58 dakika sürdü. Evrenin ısı ölümüne ulaşmadan önce durağanlığı çözmek için kuyruğu hatırlamanız gerekir; aksi takdirde, sonuçta bir O(n!!)çözüm elde edersiniz O(n!). (Benim golf O(n*2^n)yerine O(2^n), çünkü tam olarak kaldırma yerine kaldırmaya okadar tüm desenleri üretir . Düzeltmesi kolay, ancak birkaç karaktere mal olacak.)rr
rici
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.