ทำฉากสี่เหลี่ยม


33

โปรแกรมเมอร์ทุกคนรู้ว่าวงเล็บ[]{}()<>สนุกมาก เพื่อทำให้ความสนุกทวีความรุนแรงมากขึ้นกลุ่มของวงเล็บสานแบบสานสามารถเปลี่ยนเป็นไดอะแกรมน่ารักและคลุมเครือ

[{][<(]})>(())สมมติว่าคุณมีสตริงที่มีวงเล็บสมดุลเช่น ขั้นตอนที่หนึ่งคือการหมุนสตริง 45 องศาตามเข็มนาฬิกา (ใน Mathematica สามารถทำได้เกือบRotate[ur_string,-pi/4]) นี่คือผลลัพธ์ของขั้นตอนแรก:

[
 {
  ]
   [
    <
     (
      ]
       }
        )
         >
          (
           (
            )
             )

ถัดไปเพิ่มช่องว่างในแนวทแยงระหว่างตัวละครแต่ละตัว

[

  {

    ]

      [

        <

          (

            ]

              }

                )

                  >

                    (

                      (

                        )

                          )

จากนั้นเริ่มต้นด้วยวงเล็บปีกกาซ้ายสุดและวาดสี่เหลี่ยมระหว่างมันและคู่ของมันในอาชญากรรม

+---+
|   |
| { |
|   |
+---+

      [

        <

          (

            ]

              }

                )

                  >

                    (

                      (

                        )

                          )

ทำซ้ำขั้นตอนนี้กับวงเล็บแต่ละคู่โดยเขียนทับอักขระก่อนหน้าด้วย+s ถ้าจำเป็น

+---+
|   |
| +-+---------+
| | |         |
+-+-+         |
  |           |
  |   [       |
  |           |
  |     <     |
  |           |
  |       (   |
  |           |
  |         ] |
  |           |
  +-----------+

                )

                  >

                    (

                      (

                        )

                          )

ทำต่อไปจนกว่าคุณจะทำทุกอย่างให้ดีและเป็นรูปสี่เหลี่ยมจัตุรัส

+---+
|   |
| +-+---------+
| | |         |
+-+-+         |
  |           |
  |   +-----+ |
  |   |     | |
  |   | +---+-+---+
  |   | |   | |   |
  |   | | +-+-+-+ |
  |   | | | | | | |
  |   +-+-+-+ | | |
  |     | |   | | |
  +-----+-+---+ | |
        | |     | |
        | +-----+ |
        |         |
        +---------+

                    +-----+
                    |     |
                    | +-+ |
                    | | | |
                    | +-+ |
                    |     |
                    +-----+

อินพุต

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

เอาท์พุต

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

เป้าหมาย

นี่คือโค้ดกอล์ฟซึ่งมีจำนวนน้อยที่สุดที่ชนะ


1
เราต้องจัดการกับการซ้อนของวงเล็บประเภทเดียวกันหรือไม่? เช่น[[]]เราจะเอาท์พุทสแควร์สสองตัวที่ทับซ้อนกันหรือว่าเราต้องเอาท์พุทหนึ่งสแควร์ภายในอีกอันหนึ่งได้ไหม?
ความผันผวน

2
หนึ่งตารางอยู่ข้างในอีกด้านหนึ่ง ฉันจะปรับตัวอย่างของฉัน แก้ไข: เสร็จแล้ว
PhiNotPi

คำตอบ:


7

JavaScript (ES6), 269 ​​274 278 296 261 ไบต์

แก้ไขที่บันทึกไว้ 4 ไบต์ thx @Neil

x=>[...x].map(c=>{g.push([],[]),z='<{[(>}])'.indexOf(c);if(z>3)for(j=a=o[z-4].pop();j<=b;j++)S(j,a,'|'),S(j,b,'|'),S(a),S(b);else o[z].push(b);b+=2},S=(y,x=j,c='-')=>g[y][x]=g[y][x]?'+':c,o=[[],[],[],[]],g=[],b=0)&&g.map(r=>[...r].map(c=>c||' ').join``).join`
`

ทดสอบ

F=x=>[...x].map(c=>{g.push([],[]),z='<{[(>}])'.indexOf(c);if(z>3)for(j=a=o[z-4].pop();j<=b;j++)S(j,a,'|'),S(j,b,'|'),S(a),S(b);else o[z].push(b);b+=2},S=(y,x=j,c='-')=>g[y][x]=g[y][x]?'+':c,o=[[],[],[],[]],g=[],b=0)&&g.map(r=>[...r].map(c=>c||' ').join``).join`
`

// Less golfed
U=x=>(
  S = (y,x=j,c='-')=>g[y][x]=g[y][x]?'+':c,
  o = [[],[],[],[]],
  g = [],
  b = 0,
  [...x].map(c=>
  {
    g.push([],[]),
    z='<{[(>}])'.indexOf(c);
    if(z>3)
      for(j = a =o[z-4].pop(); j <= b; j++)
        S(j,a,'|'),
        S(j,b,'|'),
        S(a),
        S(b)
    else
      o[z].push(b);
    b += 2
  }),
  g.map(r=>
    [...r].map(c=>c||' ').join``
  ).join`\n`
)

function test() {
  O.textContent=F(I.value)
}

test()
Input:<input id=I value='[{][<(]})>(())' oninput='test()'>
<pre id=O></pre>


ทำไมไม่[...r].map?
Neil

[...r].map(c=>c||' ')ยังดีกว่า
Neil

@ ไม่มีฉันไม่สามารถใช้r.mapเพราะ r เป็นอาร์เรย์เบาบางและแผนที่ข้ามองค์ประกอบที่ขาดหายไป ดังนั้นตอนนี้ผมใช้กรัมที่เต็มไป (และมีเป็นหลายแถวเป็นคอลัมน์ในการส่งออก)
edc65

2
ฉันไม่ได้พูดว่าr.mapฉันพูด[...r].mapและ[...r]ไม่ใช่อาร์เรย์หร็อมแหร็มตามที่คุณพูดถึงตัวเองในcodegolf.stackexchange.com/a/61505ความคิดเห็นที่ 5
Neil

@ ไม่มีฉันคิดถึงสิ่งนั้น ... ดูเหมือนว่าจะเป็นคำใบ้ที่ดีขอบคุณ
edc65

4

Python 3, 226

n,p,*t=0,[],0,[],[],[],[]
for b in input():
 r=t[ord(b)//30];r+=[n];n+=2
 if b in'])}>':p+=[r[-2:]];del r[-2:]
R=range(n-1)
for y in R:print(''.join(' -|+'[sum((y in q)+2*(x in q)for q in p if x>=q[0]<=y<=q[1]>=x)]for x in R))

ตัวอย่าง คำอธิบาย:

n,p,*t=0,[],0,[],[],[],[]   # n -> counter for input
                            # p -> bracket pairs
                            # t -> four stacks [unused, (), <>, [], {}]

for b in input():           # for each bracket b of input
  r=t[ord(b)//30];          # r -> alias for b's stack
  r+=[n];                   # push bracket's index
  n+=2                      # increase counter by 2 (to add diagonal gaps)

  if b in'])}>':            # if b is a closing bracket
    p+=[r[-2:]];            # pair the top 2 brackets on stack
    del r[-2:]              # pop them from stack

R=range(n-1)                # n-1 is now the width/height of output

for y in R:
  print(''.join(' -|+'[
    sum((y in{a,b})+2*(x in{a,b})for a,b in p if x>=a<=y<=b>=x)
  ]for x in R))

# three nested loops:
# 1) for each line y
#   2) for each character x
#     3) for each bracket pair (a, b)

if x>=a<=y<=b>=x
# if x or y isn't in the inclusive range [a, b], we can skip it

(y in{a,b})
# if y is a or b, then the character lies on a horizontal edge of that square
# so we add 1 to the sum

2*(x in{a,b})
# if x is a or b, then the character lies on a vertical edge of that square
# so we add 2 to the sum

' -|+'[sum()]
# if it lies on a single edge, the sum will be 1 or 2 -> '-' or '|'
# if it lies on two edges, the sum will be 1 + 2 == 3 -> '+'

คุณสามารถบันทึก 2 ไบต์ได้โดยไม่แกะคู่วงเล็บในบรรทัดสุดท้าย
ความผันผวน

2

pb - 449 ไบต์

^w[B!0]{w[B=40]{b[39]}t[B]w[B!0]{w[B=T]{^b[1]}w[B=T+1]{^b[1]}w[B=T+2]{^b[2]}^[Y]^>}<[X]^w[B!1]{>}t[1]b[0]w[T!0]{>w[B=1]{t[T+1]b[0]}w[B=2]{t[T-1]b[0]}}b[3]vw[B!0]{>}^w[B!3]{b[0]<}b[0]vb[1]>[X]vv[X]b[43]t[X]^[Y]^<[X]w[B=0]{>}>[X]vv[X]b[43]w[Y!T-1]{vw[B=45]{b[43]}w[B=0]{b[124]}}vb[43]t[1]>w[B!43]{t[T+1]w[B=124]{b[43]}w[B=0]{b[45]}>}w[T!0]{^t[T-1]w[B=45]{b[43]}w[B=0]{b[124]}}w[B!43]{w[B=124]{b[43]}w[B=0]{b[45]}<}<[X]^[Y]^w[B=0]{>}b[0]>w[B=1]{b[0]>}}

ฉันตื่นเต้นมากเมื่อฉันอ่านสิ่งนี้เพราะฉันมีภาษาที่พิมพ์โดยตรงไปยังตำแหน่ง! ความท้าทายเกี่ยวกับผลลัพธ์การวางตำแหน่งควรสั้นและง่าย!

จากนั้นฉันก็จำได้ว่า pb นั้นถูกลมพัดยาวอยู่ดี

ด้วยความคิดเห็น:

^w[B!0]{
    w[B=40]{b[39]}                       # change ( to ' to make closing bracket calculation work
    t[B]

    # this used to just find the first matching bracket
    # but then op clarified we had to use depth
    # whoops
    # <fix>

    w[B!0]{
        w[B=T]{^b[1]}                        # put a 1 above opening brackets of this type
        w[B=T+1]{^b[1]}                      # same as before, but ugly hack to make ( work
        w[B=T+2]{^b[2]}                      # put a 2 above closing brackets of this type
        ^[Y]^                                # return to input line
    >}
    <[X]^w[B!1]{>}t[1]b[0]               # set T to 1 above the opening bracket
    w[T!0]{>                             # until T (depth) == 0:
        w[B=1]{t[T+1]b[0]}                   # add 1 to T if 1
        w[B=2]{t[T-1]b[0]}                   # subtract 1 from T if 2
    }
    b[3]                                 # when T is 0, we've found the right one
    vw[B!0]{>}                           # go to the end of the input
    ^w[B!3]{b[0]<}b[0]v                  # clean up the row above
    # </fix>

    b[1]                                 # replace it with 1 so it's not confusing later
    >[X]vv[X]b[43]t[X]                   # put a + at its output position and save coord
    ^[Y]^<[X]w[B=0]{>}>[X]vv[X]b[43]     # put a + at opening bracket's output position
    w[Y!T-1]{v
        w[B=45]{b[43]}                       # replace - with +
        w[B=0]{b[124]}                       # otherwise put |
    }
    vb[43]                               # put a + at lower left corner
    t[1]                                 # count side length + 1
    >w[B!43]{
        t[T+1]
        w[B=124]{b[43]}                      # replace | with +
        w[B=0]{b[45]}                        # otherwise put -
    >}
    w[T!0]{^                             # create right side
        t[T-1]
        w[B=45]{b[43]}
        w[B=0]{b[124]}
    }
    w[B!43]{                             # create top side
        w[B=124]{b[43]}                      # this replacement saves us from putting the last + explicitly
                                             # which is why we counted the side length + 1, to get that 
                                             # extra char to replace
        w[B=0]{b[45]}
    <}
    <[X]^[Y]^w[B=0]{>}b[0]>w[B=1]{b[0]>}# Go to next character (skipping 1s)
}

ฉัน ... แค่ ... ไม่สามารถ ...
Cyoce


1

ทับทิม, 268

->z{a=(2..2*t=z.size).map{'  '*t}
g=->y,x{a[y][x]=(a[y][x-1]+a[y][x+1]).sum>64??+:?|}
2.times{|h|s=z*1
t.times{|i|c=s[i]
c>?$&&(j=s.index(c.tr('[]{}()<>','][}{)(><'))
(m=i*2).upto(n=j*2){|k|k%n>m ?g[k,m]+g[k,n]:h<1&&a[k][m..n]=?++?-*(n-m-1)+?+}
s[i]=s[j]=?!)}}
puts a}

ungolfed ในโปรแกรมทดสอบ

f=->z{
  a=(2..2*t=z.size).map{'  '*t}                       #make an array of strings of spaces
  g=->y,x{a[y][x]=(a[y][x-1]+a[y][x+1]).sum>64??+:?|} #function for printing verticals: | if adjacent cells spaces (32+32) otherwise +

  2.times{|h|                                         #run through the array twice
    s=z*1                                             #make a duplicate of the input (*1 is a dummy operation to avoid passing just pointer)
    t.times{|i|                                       #for each index in input
    c=s[i]                                            #take the character
    c>?$&&(                                           #if ascii value higher than for $
      j=s.index(c.tr('[]{}()<>','][}{)(><'))          #it must be a braket so find its match
      (m=i*2).upto(n=j*2){|k|                         #loop through the relevant rows of array
        k%n>m ?g[k,m]+g[k,n]:                         #if k!=n and k!m draw verticals
        h<1&&a[k][m..n]=?++?-*(n-m-1)+?+              #otherwise draw horizontals (but only on 1st pass)
      }
      s[i]=s[j]=?!)                                   #we are done with this set of brackets, replace them with ! so they will be ignored in next call of index  
    }
  }
  puts a
}


z=gets.chop
f[z]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.