วงเล็บประสาน


30

เขียนโปรแกรมหรือฟังก์ชั่นที่รับสายอักขระแปดไบต์ที่ประกอบด้วยอักขระตัว()[]{}<>ใดตัวหนึ่งที่จัดเรียงในลักษณะใด ๆ ซึ่งประเภทวงเล็บทั้งสี่นั้นตรงกัน ตัวอย่างเช่น]<([){}>เป็นอินพุตที่ไม่ถูกต้องเนื่องจากวงเล็บเหลี่ยมไม่ตรงกัน

พิมพ์หรือกลับจำนวนเต็มจาก0การ6ระบุว่าวิธีการที่หลายหกจับคู่ที่เป็นไปได้ในสี่ประเภทตัวยึดประสาน คู่ของประเภท Bracket จะถือว่ามีการเชื่อมต่อกันหากมีวงเล็บหนึ่งอันของประเภทหนึ่งเกิดขึ้นระหว่างวงเล็บของประเภทอื่น ดังนั้น([)]และ[(])มีการเชื่อมต่อกัน แต่()[], [](), ([])และ[()]ไม่ได้

รหัสที่สั้นที่สุดในหน่วยไบต์ชนะ

ตัวอย่างอินพุต / เอาท์พุต

()[]{}<> : 0
([{<>}]) : 0
<>{[]}() : 0
{<>([])} : 0
<(>)[{}] : 1
<[({)}]> : 1
[{<}]>() : 2
{<>([}]) : 2
<{(>})[] : 3
[(]<){>} : 3
<([>{)}] : 4
(<{[>})] : 4
(<[{)>}] : 5
<{[(>})] : 5
[{<(]}>) : 6
(<{[)>}] : 6

คำตอบ:


17

CJam, 18

l7~f&_f{\/~;&}s,2/

ขอบคุณ isaacg สำหรับไอเดียการตีกอล์ฟ :)
ลองออนไลน์หรือลองทุกตัวอย่าง

คำอธิบาย:

l         read a line of input
7~f&      clear the lowest 3 bits of each character
           the goal is to convert brackets of the same type to the same char
_         duplicate the resulting string, let's call it S
f{…}      for each character in S, and S (the char and S are pushed every time)
  \       swap the character with S
  /       split S around that character, resulting in 3 pieces:
           before, between, after
  ~       dump the pieces on the stack
  ;       pop the last piece
  &       intersect the first 2 pieces
          after the loop, we have an array of strings
          containing the chars interlocking to the left with each char of S
s         join all the string into one string
,         get the string length
2/        divide by 2, because S has duplicated characters

1
โอ้คุณเป็นคนที่สร้าง CJam เหรอ? คุณเป็นหนี้ฉันสำหรับคำตอบทั้งหมดที่ฉันแพ้ซึ่งคำตอบของ CJam พ่ายแพ้! ;)
kirbyfan64sos

6
@ kirbyfan64sos ดีคุณควรเริ่มเรียนรู้มันเช่นกันหากคุณต้องการที่จะชนะ :)
aditsu

9
7~f&? ฉันชอบคำตอบนี้แล้วและฉันยังไม่ได้อ่านส่วนที่เหลือ
Dennis

11

Python 2, 163 ไบต์

def f(b,e='([{<)]}>',q=range(4)):
 b=[b[b.index(e[j])+1:b.index(e[j+4])]for j in q]
 print sum(sum(abs(b[k].count(e[j])-b[k].count(e[j+4]))for j in q)for k in q)/2

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

ฉันแน่ใจว่ามันสามารถเล่นกอล์ฟได้มากขึ้นโดยนักกอล์ฟที่ดีกว่าฉัน


31
มันเกิดขึ้น Calvin โพสต์คำตอบ เวลาสิ้นสุดมาถึงเราแล้ว
Alex A.

4

GNU sed -r, 147

เอาต์พุตอยู่ในเกณฑ์เดียวกันตามเมตาคำตอบนี้

y/([{</)]}>/
s/.*/\t& & & & /
:b
y/)]}>/]}>)/
s/\S*>(\S*)>\S* /\1\t/
t
s/\S* //
:
s/(\t\S*)(\S)(\S*)\2(\S*\t)/\1\3\4/
t
s/\S *$/&/
tb
s/\s//g
s/../1/g

หมายเหตุ: แทนที่\tด้วยtabตัวอักษรจริงเพื่อให้ได้คะแนนที่ถูกต้อง อย่างไรก็ตามโปรแกรมจะทำงานทั้งสองทางกับ GNU sed

ลองมันออนไลน์


3

Perl, 77 ไบต์

76 รหัส + 1 สวิตช์

perl -pe 'y/)]}>/([{</;for$x(/./g){$h{$x="\\$x"}++&&s!$x(.*)$x!$z+=length$1,$1!e}$_=$z'

รับอินพุตจาก STDIN และโปรแกรมต้องเริ่มต้นใหม่สำหรับทุกอินพุต

คำอธิบาย

  1. แทนที่วงเล็บปิดทั้งหมดด้วยเครื่องหมายเปิด ( y/.../.../)
  2. จากนั้นสำหรับอักขระทุกตัวในสตริงอินพุต ( for$x...) ให้เพิ่มตัวนับสำหรับอักขระ ( $h{$x}++)
  3. หากนี่เป็นครั้งที่สองที่เราเห็นตัวละครให้หาระยะห่างระหว่างเหตุการณ์ทั้งสอง ( length $1) และลบทั้งสองตัวนี้ออกจากสตริง ตัวอย่างเช่นถ้าสตริงก็([{([{<<มีตัวละครทั้งสอง[และ{ระหว่างสอง(s หลังจาก(ประมวลผลแล้วสตริงจะกลายเป็น[{[{<<และเราบวก 2 เข้ากับจำนวนทั้งหมด ( $z) ของวงเล็บประสาน
  4. ผลลัพธ์ถูกนำมาจาก$z( $_=$z)

3

Pyth, 20 ไบต์

JmC/CdTzlsm@FPcsJd{J

ชุดทดสอบ

JmC/CdTz: ขั้นแรกวิธีนี้จะแปลงคู่สัญลักษณ์แต่ละคู่ให้เป็นอักขระเดียวโดยแมปอักขระอินพุตแต่ละตัวเป็นรหัสอักขระ ( Cd) หารด้วย 10 ( / T) ซึ่งเหมือนกันสำหรับแต่ละคู่ แต่แตกต่างกันระหว่างคู่ทั้งหมด หมายเลขผลลัพธ์ถูกแปลงกลับเป็นอักขระเพื่อให้เปิดเผยภายหลัง ( C) Jรายการผลลัพธ์ของตัวละครจะถูกบันทึกไป

lsm@FPcsJd{J: ตอนนี้เราจับคู่อักขระที่ไม่ซ้ำกันในJ( {J) เราเริ่มต้นด้วยการสับสตริงที่เกิดขึ้นจากการเชื่อมต่อJโดยใช้อักขระปัจจุบันเป็น delimeter ( csJd) เครื่องหมายวงเล็บคู่ทับซ้อนคู่ปัจจุบันถ้าปรากฏในกลุ่มที่สองและกลุ่มที่หนึ่งหรือที่สาม เพื่อหลีกเลี่ยงการนับซ้ำเราจะนับกรณีตัวแรกและตัวที่สอง ดังนั้นเราจึงลบกลุ่มที่สาม ( P) และหาจุดตัดของกลุ่มที่เหลือ ( @F) สุดท้ายเราต่ออักขระทับซ้อน ( s) และพิมพ์ความยาวของ resut ( l)


3

Python 3, 107

t=0
s=""
for x in input():s+=chr(ord(x)&~7)
for x in s:a=s.split(x);t+=len(set(a[0])&set(a[1]))
print(t//2)

อิงจากโซลูชั่น CJam ของฉันอย่างหลวม ๆ


3

เรติน่า , 128 108 64 62 55 ไบต์

(T`)]>}`([<{
(\D)(.*)\1(.*)
\n$2\n$3
(?=(\D).*\n.*\1)
1
\n
<empty>

ในกรณีที่<empty>แสดงให้เห็นถึงบรรทัดต่อท้ายที่ว่างเปล่า สำหรับวัตถุประสงค์ในการนับให้ใส่แต่ละบรรทัดในไฟล์แยกกันและแทนที่\nด้วยอักขระตัวป้อนบรรทัดจริง เพื่อความสะดวกคุณสามารถใช้รหัสที่เทียบเท่านี้กับการ-sตั้งค่าสถานะจากไฟล์เดียว:

(T`)]>}`([<{
(\D)(.*)\1(.*)
#$2#$3
(?=(\D)[^#]*#[^#]*\1)
1
#
<empty>

เอาท์พุทเป็นเอก

คำอธิบาย

ตัวแรก(บอกว่า Retina จะรันโค้ดทั้งหมดในลูปจนกว่าการวนซ้ำจะหยุดเปลี่ยนสตริง ในกรณีนี้มันจะวนซ้ำสี่ครั้งหนึ่งครั้งสำหรับแต่ละวงเล็บ

T`)]>}`([<{

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

(\D)(.*)\1(.*)
\n$2\n$3

สิ่งนี้จะแทนที่วงเล็บซ้ายสุดด้วยบรรทัดใหม่ เราใช้\Dเพื่อแยกความแตกต่างของวงเล็บจาก1s เราเพิ่มในลูปสำหรับการนับในภายหลัง (.*)ที่มั่นใจว่าท้ายที่สุดว่ามีเพียงหนึ่งคู่จะถูกแทนที่ (เพราะการแข่งขันไม่สามารถทับซ้อน)

(?=(\D).*\n.*\1)
1

regex ทั้งหมดอยู่ใน lookahead ดังนั้นนี้ตรงกับตำแหน่ง โดยเฉพาะอย่างยิ่งมันตรงกับหนึ่งตำแหน่งสำหรับวงเล็บแต่ละคู่ซึ่งถูกคั่นด้วยวงเล็บอื่น ๆ ที่เราเพิ่งเปลี่ยนเป็นบรรทัดใหม่ A 1ถูกแทรกลงในแต่ละตำแหน่งเหล่านี้ เราสามารถออกจากที่1นั่นเพราะพวกเขาไม่ส่งผลกระทบต่อ regexes อื่น ๆ (เพราะ\Dมั่นใจว่าเราไม่ตรงกับพวกเขาโดยไม่ได้ตั้งใจ)

\n
<empty>

สุดท้ายเราลบ newlines (เช่นตัวแทนสำหรับประเภทปัจจุบันของวงเล็บ) - ซึ่งหมายความว่าเราได้ลดปัญหาที่เหลืออยู่เป็นสตริงความยาว 6 ที่มีเพียง 3 ประเภทของวงเล็บ แต่อย่างอื่นมันทำงานเหมือนกันอย่างแน่นอน

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


2

JavaScript (ES7), 121 117 ไบต์

x=>(a=b=0,[for(c of x)for(d of'1234')(e=c.charCodeAt()/26|0)==d?a^=1<<d:b^=(a>>d&1)<<d*4+e],f=y=>y&&y%2+f(y>>1))(b)/2

ว้าว. นั้นน่าสนุก. ฉันร่างแนวคิดคำตอบเมื่อความท้าทายนี้ออกมาเป็นครั้งแรก แต่มันมีความยาวเกิน 150 ไบต์และฉันไม่ต้องการพยายามตีกอล์ฟ ฉันวิ่งข้ามความคิดนี้ในสมุดบันทึกของฉันเมื่อวานนี้และตัดสินใจว่าจะไม่หยุดคิดจนกว่าฉันจะตีกอล์ฟให้เต็มที่ ฉันลงเอยด้วยการเขียนอัลกอริธึมใหม่ทั้งหมดสองอย่างโดยเริ่มแรกนั้นสั้นลงหลายไบต์หลังจากเล่นกอล์ฟไปประมาณ 25 ไบต์ด้วยการแฮ็คบิตจำนวนหนึ่ง

มันทำงานอย่างไร

ครั้งแรกที่เราตั้งค่าตัวแปรaและการb เป็นอาร์เรย์ไบนารี 4 บิตซึ่งคู่วงเล็บเราอยู่ในขณะนี้และเป็นอาร์เรย์ไบนารี 16 บิตซึ่งคู่วงเล็บถูกเชื่อมโยงเข้าด้วยกัน0ab

ต่อไปเราจะห่วงผ่านตัวละครแต่ละตัวcในxแต่ละถ่านในd '0123'ครั้งแรกที่เรากำหนดประเภทของตัวยึดอยู่กับc e=c.charCodeAt()/26-1|0รหัสถ่านฐานสิบของวงเล็บแต่ละประเภทมีดังนี้:

() => 40,41
<> => 60,62
[] => 91,93
{} => 123,125

โดยการหารด้วย 26 การลบ 1 และการปูพื้นเราจับคู่สิ่งเหล่านี้กับ 0, 1, 2 และ 3 ตามลำดับ

dต่อไปเราจะตรวจสอบว่าหมายเลขนี้จะเท่ากับมูลค่าปัจจุบันของ ถ้าเป็นเรามีทั้งเข้าหรือออกจากdประเภทวงเล็บ, th ดังนั้นเราจึงพลิกdบิตในลำดับที่มีa a^=1<<dหากยังไม่ได้ แต่เรามีอยู่ภายในdชนิดยึดวันที่เราต้องพลิกeบิตบริบูรณ์ในdวันที่มาตรา 4 bบิต ทำเช่นนี้เพื่อ:

b^=(a>>d&1)<<d*4+e

(a>>d&1)ผลตอบแทนบิตในลำดับที่d aถ้าเราอยู่ในdประเภทวงเล็บปีกกานี่จะส่งคืน 1 มิฉะนั้นจะส่งคืน 0 ถัดไปเราเลื่อนซ้ายไปทีละd*4+eบิตและ XOR bตามผลลัพธ์ หากเราอยู่ในdประเภทวงเล็บปีกกา XOR นี้จะเป็นd*4+eบิตที่สามของb; มิฉะนั้นจะไม่ทำอะไรเลย

ในตอนท้ายของการวนซ้ำทั้งหมดbจะมีจำนวน 1 บิตเท่ากับค่าส่งคืนที่ต้องการสองเท่า แต่เรายังต้องหาจำนวนบิตนี้ นั่นคือที่fมาของฟังก์ชั่นย่อย:

f=y=>y&&y%2+f(y>>1)

ถ้าyเป็น 0 นี้ก็กลับ 0 มิฉะนั้นก็จะใช้เวลาบิตสุดท้ายของyด้วยy%2แล้วเพิ่มผลของการทำงานทั้งหมด แต่บิตสุดท้ายที่yผ่านการทำงานอีกครั้ง ตัวอย่างเช่น:

f(y)         => y && y%2 + f(y>>1)
f(0b1001101) =>       1  + f(0b100110) = 4
f(0b100110)  =>       0  + f(0b10011)  = 3
f(0b10011)   =>       1  + f(0b1001)   = 3
f(0b1001)    =>       1  + f(0b100)    = 2
f(0b100)     =>       0  + f(0b10)     = 1
f(0b10)      =>       0  + f(0b1)      = 1
f(0b1)       =>       1  + f(0b0)      = 1
f(0b0)       => 0                      = 0

เราวิ่งbผ่านฟังก์ชั่นนี้และหารผลลัพธ์ด้วย 2 และมีคำตอบของเรา


1

Oracle SQL 11.2, 206 ไบต์

WITH v AS(SELECT b,MIN(p)i,MAX(p)a FROM(SELECT SUBSTR(TRANSLATE(:1,'])>}','[(<{'),LEVEL,1)b,LEVEL p FROM DUAL CONNECT BY LEVEL<9)GROUP BY b)SELECT COUNT(*)FROM v x,v y WHERE x.i<y.i AND x.a<y.a AND y.i<x.a;

เลิกเล่น:

WITH v AS( -- Compute min and max pos for each bracket type
           SELECT b,MIN(p)i,MAX(p)a 
           FROM   ( -- replace ending brackets by opening brakets and split the string  
                    SELECT SUBSTR(TRANSLATE(:1,'])>}','[(<{'),LEVEL,1)b,LEVEL p 
                    FROM DUAL 
                    CONNECT BY LEVEL<9
                  )
           GROUP BY b
         )
SELECT COUNT(*)
FROM   v x,v y
WHERE  x.i<y.i AND x.a<y.a AND y.i<x.a -- Apply restrictions for interlocking brackets  
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.