Складіть квадратні дужки


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?
Ніл

А ще краще, [...r].map(c=>c||' ').
Ніл

@Neil Я не можу використовувати, r.mapоскільки r - це розріджений масив, а карта пропускає відсутні елементи. Отже, я зараз використовую g, який заповнюється (а стільки рядків, скільки стовпців у виході)
edc65

2
Я не сказав r.map, я сказав [...r].map, і [...r]НЕ є рідкісним масивом, як ви згадали про себе в коді codegolf.stackexchange.com/a/61505 коментар 5.
Ніл

@Neil Я пропустив це ... здається, приємний натяк, дякую
edc65

4

Пітон 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}

unolfolf у тестовій програмі

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]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.