Viết chương trình thay thế bằng khoảng trắng niềng răng trong trường hợp niềng răng ở những nơi gây ứ máu


17

Bạn là một người quản lý dự án. Một ngày nọ, một trong những lập trình viên của bạn phát điên ( không phải lỗi của bạn ) và lấy tất cả các biểu thức trong cơ sở mã và thêm dấu ngoặc ngẫu nhiên vào chúng, trước khi thoát ra tại chỗ, nói về sự bất tài của bạn ( cũng không phải lỗi của bạn ). Đây sẽ là một sửa chữa dễ dàng, tuy nhiên, vì một số lý do bạn không sử dụng kiểm soát sửa đổi ( hoàn toàn không phải lỗi của bạn ). Và vì một số lý do, không ai trong số các lập trình viên khác muốn trải qua mọi biểu thức để sửa các dấu ngoặc không khớp ( nhân tiện, đó không phải là lỗi của bạn ). Lập trình viên những ngày này, bạn nghĩ cho chính mình. Bạn sẽ phải tự làm điều đó. Kinh dị! Những nhiệm vụ như vậy được cho là ở bên dưới bạn ...

Đầu vào sẽ là một dòng duy nhất, sẽ chứa một số dấu ngoặc trái ( ( [ {) và dấu ngoặc phải ( ) ] }). Nó cũng có thể, nhưng không phải lúc nào cũng chứa các bình luận ( /* */) và chuỗi ký tự ( " "hoặc ' ') và các số, chữ cái hoặc ký hiệu khác nhau.

Sẽ có ít nhất một dấu ngoặc (bên ngoài một bình luận hoặc chuỗi ký tự) không có sự đối lập (bên ngoài một bình luận hoặc chuỗi ký tự). Ví dụ, một sai lầm }mà không có {trước. Một ví dụ khác: một (cái không có )sau đó. Chương trình của bạn sẽ thay thế bằng một khoảng trống số lượng dấu ngoặc tối thiểu cần thiết để làm cho dấu ngoặc khớp với nhau.

Ví dụ:

(4 + (2 + 3))]==> (4 + (2 + 3)) (dấu ngoặc vuông ở cuối)
][][[]]==> [][[]](dấu ngoặc vuông ở đầu)
("Hel(o!"))==> ("Hel(o!") (dấu ngoặc đơn ở cuối)
( /* )]*/==> /* )]*/ (dấu ngoặc đơn ở đầu)
{()]==> () (dấu ngoặc nhọn và dấu ngoặc vuông)

  • Có thể lấy đầu vào từ bất kỳ cách nào thuận tiện nhất (STDIN, đối số dòng lệnh, đọc từ tệp, v.v.)
  • Nếu có nhiều hơn một cách để giải quyết sự không phù hợp với cùng số lần xóa, thì có thể chấp nhận được.
  • Sẽ chỉ có sự không phù hợp trong ngoặc. Chuỗi ký tự và bình luận sẽ luôn luôn được hình thành chính xác.
  • Tiêu đề đến từ chủ đề SO này
  • Sẽ không bao giờ có bất kỳ trích dẫn nào trong các bình luận, trích dẫn trong trích dẫn, bình luận trong các bình luận, hoặc bình luận trong các trích dẫn.

Đây là mã golf, vì vậy số byte tối thiểu sẽ thắng. Đặt câu hỏi trong ý kiến ​​nếu đặc điểm kỹ thuật không rõ ràng.


Rất tiếc, chỉnh sửa của chúng tôi loại va chạm ở đó. : P Mọi thứ nên được sửa ngay bây giờ.
Doorknob

@Doorknob Cảm ơn vì điều đó, nhân tiện. Không biết làm thế nào để ngăn chặn SE từ lau không gian.
absinthe

Chúng ta có phải xử lý các công cụ thoát trong chuỗi ký tự (ví dụ ("foo (\") bar")) không?
Doorknob

1
Tôi sẽ lập luận rằng đầu ra chính xác {{(})phải là { } hoặc tương đương, vì kịch bản mở đầu ngụ ý rằng mã đang hoạt động để bắt đầu và {(})được tính là dấu ngoặc không khớp trong mọi ngôn ngữ lập trình mà tôi biết (nghĩa là "gây ra sự ngưng trệ" ??). Nhưng, sau đó, tôi đã viết một câu trả lời, vì vậy tôi thiên vị.
DLosc

3
Tôi hiểu rồi. Đoán tôi chỉ là không đủ năng lực. ;)
DLosc

Câu trả lời:


6

Ruby, 223 ký tự

Cái này hóa ra hơi dài.

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}

Những gì nó làm là lấy ra các chuỗi và nhận xét trước, vì vậy chúng không được tính (và đưa chúng trở lại sau).

Sau đó, nó đi qua chuỗi ký tự theo ký tự. Khi nó tìm thấy một cú đúp mở, nó lưu vị trí của nó. Khi tìm thấy một dấu ngoặc nhọn, nó bật ra từ mảng lưu trữ dấu ngoặc mở tương ứng.

Nếu poptrả về nil(nghĩa là không có đủ dấu ngoặc mở), nó sẽ loại bỏ dấu ngoặc đóng. Sau khi hoàn thành toàn bộ việc này, nó sẽ loại bỏ các dấu ngoặc mở thêm còn lại (nghĩa là không có đủ dấu ngoặc đóng).

Vào cuối chương trình, nó đặt tất cả các chuỗi và nhận xét lại và xuất chúng.

Ung dung:

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

Đây là ấn tượng nghiêm trọng. Một câu hỏi, mặc dù: nó sẽ vẫn hoạt động cho một đầu vào như thế (("string"/*comment*/)"string"nào? Nếu tôi đang đọc (phiên bản không được chỉnh sửa) một cách chính xác, bạn thay thế các chuỗi và nhận xét bằng chỉ mục của chúng trong unparsedmảng, điều này sẽ dẫn đến một sự thay thế như thế ((12)3và sau đó tìm kiếm một chỉ mục không tồn tại 12(hoặc 11). Tôi thấy phiên bản golf chỉ sử dụng shift, nhưng có thể nó vẫn không có vấn đề tương tự?
DLosc

4

Trăn 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

Thử mọi cách xóa có thể, bắt đầu với những lần nhỏ hơn, cho đến khi tìm thấy một trong đó niềng răng được cân bằng. (Theo đó tôi có nghĩa là hoàn toàn cân bằng: {{(})sản xuất ( ), không {(}).)

Phiên bản đầu tiên sử dụng chức năng tạo đệ quy, nó thực sự tuyệt nhưng cũng rất dài. Phiên bản này thực hiện tìm kiếm đầu tiên đơn giản bằng cách sử dụng hàng đợi. (Vâng, đó là thuật toán thời gian giai thừa. Vấn đề là gì ?: ^ D)


Tôi thích cái này vì nó thực sự tìm thấy loại bỏ ít nhất và tạo ra các biểu thức lồng nhau chính xác, nhưng nhận xét cuối cùng của @vonilya cho thấy việc lồng chính xác không quan trọng. Tuy nhiên, nó thực sự chậm nếu cần phải tháo rất nhiều niềng răng.
rici

2

C - 406

Cố gắng trong C mà không sử dụng biểu thức thông thường.

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

Để biên dịch và chạy (trên máy linux):
gcc -o ngoặc
ngoặc.c ./brackets "[(])"

Trong các trường hợp không xác định như [(]), nó trả về cặp ngoặc hợp lệ cuối cùng ()


2

Trăn 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)

Giống như giải pháp của DLosc, điều này điều tra mọi cách xóa có thể, nhưng nó sử dụng chiến lược khám phá và dự phòng đệ quy nhanh hơn rất nhiều. Tôi biết rằng tốc độ không phải là một tiêu chí trong môn đánh gôn và tìm kiếm toàn diện trong mọi trường hợp theo cấp số nhân, nhưng điều này có thể xử lý các đầu vào như ({({({({({({({({(}}}}}}}}trong vài giây.


Chơi tốt, chơi tốt. Tôi đã cố gắng giảm xuống mức 317, nhưng tôi nghĩ bạn sẽ có thể vượt qua điều đó khá dễ dàng. (Trong khi đó, chương trình của tôi vẫn đang quay lưng với đầu vào ví dụ của bạn ...)
DLosc

@DLosc: Đừng nín thở :). Máy của tôi mất 58 phút để thực hiện phiên bản của mẫu đó với 6 dấu mở. Để giải quyết tình trạng ứ đọng trước khi vũ trụ đạt đến cái chết nhiệt, bạn sẽ cần phải ghi nhớ hàng đợi; nếu không, bạn kết thúc với một O(n!!)giải pháp, không O(n!). (Golf của tôi là O(n*2^n)thay vì O(2^n), vì othực sự tạo ra tất cả các mẫu có tối đa rloại bỏ, thay vì rloại bỏ chính xác . Dễ sửa, nhưng sẽ tốn một vài ký tự.)
rici
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.