เขียนโปรแกรมที่แทนที่ด้วยช่องว่างวงเล็บปีกกาในกรณีที่จัดฟันในสถานที่ทำให้ชะงักงัน


17

คุณเป็นผู้จัดการโครงการ วันหนึ่งหนึ่งของการเขียนโปรแกรมของคุณไปบ้า ( ไม่ใช่ความผิดของคุณ ) และเอาการแสดงออกทั้งหมดใน codebase และเพิ่มวงเล็บสุ่มกับพวกเขาก่อนที่จะเลิกสูบบุหรี่ในจุดที่คุยโวเกี่ยวกับการไร้ความสามารถของคุณ ( ยังไม่ใช่ความผิดของคุณ ) นี่จะเป็นการแก้ไขที่ง่ายอย่างไรก็ตามด้วยเหตุผลบางอย่างที่คุณไม่ได้ใช้การควบคุมการแก้ไข ( ไม่ใช่ความผิดทั้งหมดของคุณ ) และด้วยเหตุผลบางอย่างไม่มีโปรแกรมเมอร์คนอื่น ๆ ที่ต้องการผ่านทุกนิพจน์เพื่อแก้ไขวงเล็บที่ไม่ตรงกัน ( โดยวิธีการที่ไม่ใช่ความผิดของคุณ ) โปรแกรมเมอร์วันนี้คุณคิดกับตัวเอง คุณจะต้องทำเอง สยองขวัญ! งานดังกล่าวควรจะอยู่ภายใต้คุณ ...

อินพุตจะเป็นบรรทัดเดียวซึ่งจะมีจำนวนวงเล็บซ้าย ( ( [ {) และวงเล็บปีกกาขวา ( ) ] }) นอกจากนี้ยังอาจมีความคิดเห็น ( /* */) และตัวอักษรสตริง ( " "หรือ' ') และตัวเลขตัวอักษรหรือสัญลักษณ์ต่างๆ

จะมีตัวยึดอย่างน้อยหนึ่งตัว (นอกความคิดเห็นหรือตัวอักษรสตริง) ที่ไม่มีการกัดกร่อนที่ตรงกันข้าม (นอกความคิดเห็นหรือตัวอักษรสตริง) ตัวอย่างเช่นนักเดินทางที่}ไม่มี{ก่อนหน้า อีกตัวอย่างหนึ่ง: (ซึ่งไม่มีใน)ภายหลัง โปรแกรมของคุณจะแทนที่ด้วยช่องว่างจำนวนขั้นต่ำของวงเล็บเหลี่ยมที่จำเป็นในการทำให้วงเล็บตรง

ตัวอย่าง:

(4 + (2 + 3))]==> (4 + (2 + 3)) (วงเล็บเหลี่ยมที่ท้าย)
][][[]]==> [][[]](วงเล็บเหลี่ยมที่จุดเริ่มต้น)
("Hel(o!"))==> ("Hel(o!") (วงเล็บที่ท้าย)
( /* )]*/==> /* )]*/ (วงเล็บที่จุดเริ่มต้น)
{()]==> () (วงเล็บปีกกาและ วงเล็บเหลี่ยม)

  • อินพุตสามารถนำมาจากวิธีใดก็ได้ที่สะดวกที่สุด (STDIN อาร์กิวเมนต์บรรทัดคำสั่งการอ่านจากไฟล์ ฯลฯ )
  • หากมีมากกว่าหนึ่งวิธีในการแก้ไขความไม่ตรงกันด้วยจำนวนการลบที่เท่ากันแสดงว่ายอมรับได้
  • จะมีเฉพาะในวงเล็บไม่ตรงกัน สตริงตัวอักษรและความคิดเห็นจะเกิดขึ้นอย่างถูกต้องเสมอ
  • ชื่อมาจากเธรด SO นี้
  • จะไม่มีคำพูดใด ๆ ในความคิดเห็นคำพูดในคำพูดความคิดเห็นในความคิดเห็นหรือความคิดเห็นในคำพูด

นี่คือรหัสกอล์ฟดังนั้นจำนวนไบต์ขั้นต่ำจึงชนะ ถามคำถามในความคิดเห็นหากข้อกำหนดไม่ชัดเจน


อ๊ะการแก้ไขของเราชนกันที่นั่น : P ทุกอย่างควรได้รับการแก้ไขแล้ว
Doorknob

@ Doorknob ขอบคุณสำหรับเรื่องนี้โดยวิธีการ ไม่ทราบวิธีที่จะหยุด SE จากเช็ดช่องว่าง.
Absinthe

เราต้องจัดการกับสิ่งที่หลบหนีในตัวอักษรสตริง (เช่น("foo (\") bar"))?
Doorknob

1
ฉันจะยืนยันว่าผลลัพธ์ที่ถูกต้องสำหรับ{{(})ควรเป็น{ } หรือเทียบเท่าเนื่องจากสถานการณ์การเปิดหมายความว่ารหัสกำลังทำงานเพื่อเริ่มต้นด้วยและ{(})นับเป็นวงเล็บเหลี่ยมที่ไม่ตรงกันในทุกภาษาการเขียนโปรแกรมที่ฉันรู้ แต่หลังจากนั้นฉันเขียนคำตอบไปแล้วดังนั้นฉันจึงมีอคติ
DLosc

3
ฉันเห็น. เดาฉันแค่ไร้ความสามารถพอ ;)
DLosc

คำตอบ:


6

Ruby, 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}

สิ่งที่ต้องทำคือนำสตริงและความคิดเห็นออกมาก่อนดังนั้นพวกเขาจะไม่ถูกนับ (และทำให้พวกเขากลับมาใหม่ในภายหลัง)

จากนั้นจะผ่านตัวอักษรสตริงโดยตัวละคร เมื่อพบช่องเปิดมันจะเก็บตำแหน่งของมัน เมื่อพบว่ามีการปิดวงเล็บมันจะโผล่ออกมาจากอาเรย์จัดเก็บข้อมูลแบบเปิดของมัน

หากpopผลตอบแทนnil(เช่นมีวงเล็บปีกกาเปิดไม่เพียงพอ) มันจะลบวงเล็บปีกกาปิด หลังจากเสร็จสิ้นสิ่งนี้ทั้งหมดแล้วจะลบวงเล็บปีกกาเปิดพิเศษที่เหลืออยู่ (เช่นมีวงเล็บปีกกาปิดไม่เพียงพอ)

ในตอนท้ายของโปรแกรมมันจะใส่สตริงและความคิดเห็นทั้งหมดกลับมาและส่งออกพวกเขา

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

นี่เป็นสิ่งที่น่าประทับใจอย่างมาก แม้ว่าคำถามหนึ่งข้อ: มันจะยังใช้งานได้กับอินพุตเช่น(("string"/*comment*/)"string"หรือไม่ หากฉันกำลังอ่าน (เวอร์ชันที่ไม่อัปโหลด) อย่างถูกต้องคุณจะแทนที่สตริงและความคิดเห็นด้วยดัชนีในunparsedอาเรย์ซึ่งจะนำไปสู่การทดแทนเช่น((12)3นั้นแล้วมองหาดัชนีที่ไม่มีอยู่12(หรือ11) ฉันเห็นเวอร์ชัน golfed ใช้shiftแล้ว แต่อาจยังไม่มีปัญหาที่คล้ายกันหรือไม่
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

พยายามลบชุดที่เป็นไปได้ทุกชุดเริ่มต้นด้วยชุดที่เล็กกว่าจนกระทั่งพบชุดที่จัดฟันมีความสมดุล (โดยที่ฉันหมายถึงสมดุลอย่างถูกต้อง: {{(})ผลิต( )ไม่ใช่{(}))

รุ่นแรกใช้ฟังก์ชั่นเครื่องกำเนิดซ้ำซึ่งมันเจ๋งมาก แต่ก็ยาวมาก รุ่นนี้ทำการค้นหาแบบกว้างแรกโดยใช้คิว (ใช่มันเป็นอัลกอริทึมเวลาแบบแฟคทอเรียลปัญหาคืออะไร: ^ D)


ฉันชอบอันนี้เพราะจริง ๆ แล้วพบว่ามีการลบน้อยที่สุดและสร้างนิพจน์ที่ซ้อนกันอย่างถูกต้อง แต่ความคิดเห็นล่าสุดโดย @vonilya แสดงให้เห็นว่าการทำรังที่ถูกต้องนั้นไม่สำคัญ อย่างไรก็ตามมันช้ามากหากจำเป็นต้องถอดเครื่องมือจัดฟันออก
rici

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

@DLosc: อย่ากลั้นลมหายใจของคุณ :) เครื่องของฉันใช้เวลา 58 นาทีในการทำรูปแบบนั้นโดยมี 6 parens ที่เปิดอยู่ ในการแก้ปัญหาภาวะชะงักงันก่อนที่เอกภพจะถึงความร้อน - ร้อนคุณจะต้องบันทึกคิว มิฉะนั้นคุณท้ายด้วยวิธีการแก้ปัญหาไม่ได้O(n!!) O(n!)(สนามกอล์ฟของฉันO(n*2^n)แทนO(2^n)เพราะoจริง ๆ แล้วสร้างรูปแบบทั้งหมดที่มีถึงการเอาrออกแทนที่rการเอาออกทั้งหมดแน่นอนง่ายต่อการแก้ไข แต่มันจะเสียอักขระบางตัว)
rici
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.