Телескопічні парентези


79

Розглянемо не порожній рядок правильно збалансованих дужок:

(()(()())()((())))(())

Можна уявити, що кожна пара дужок являє собою кільце в згорнутій телескопічній конструкції . Тож давайте продовжимо телескоп:

(                )(  )
 ()(    )()(    )  ()
    ()()    (  )
             ()

Ще один спосіб поглянути на це - круглі дужки на глибині n переміщуються до рядка n , зберігаючи їх горизонтальне положення.

Ваше завдання - взяти такий рядок збалансованих дужок і створити розширену версію.

Ви можете записати програму або функцію, взявши введення через STDIN (або найближчий еквівалент), аргумент командного рядка або параметр функції та виробляючи вихід через STDOUT (або найближчий еквівалент), значення повернення або функцію (out).

Ви можете припустити, що вхідний рядок є дійсним, тобто складається лише з дужок, які правильно врівноважені.

Ви можете друкувати пробіли у кожному рядку, але не більше провідної кількості, ніж потрібно. Загалом рядки не повинні перевищувати вдвічі більше довжини вхідного рядка. Ви можете необов'язково надрукувати один зворотний рядок.

Приклади

Окрім вищенаведеного прикладу, тут є ще кілька тестових випадків (введення та вихід розділені порожнім рядком).

()

()
(((())))

(      )
 (    )
  (  )
   ()
()(())((()))(())()

()(  )(    )(  )()
   ()  (  )  ()
        ()
((()())()(()(())()))

(                  )
 (    )()(        )
  ()()    ()(  )()
             ()

Пов'язані проблеми:

  • Топографічні рядки , в яких ви просите створити те, що по суті є доповненням результату в цьому виклику.
  • Code Explanation Formatter - широке узагальнення ідей у ​​цьому виклику, опубліковане нещодавно PhiNotPi. (Насправді, оригінальним описом його ідеї було те, що надихнуло цей виклик.)

Табло лідерів

Так, у цьому було багато участі, тому ось фрагмент стека для створення як звичайного таблицю лідерів, так і огляд переможців за мовою.

Щоб переконатися, що ваша відповідь відображається, будь ласка, почніть свою відповідь із заголовка, використовуючи наступний шаблон Markdown:

# Language Name, N bytes

де Nрозмір вашого подання. Якщо ви покращите свій рахунок, ви можете зберегти старі бали у заголовку, прокресливши їх. Наприклад:

# Ruby, <s>104</s> <s>101</s> 96 bytes


17
Альтернативна назва: De-Lisp-ify рядок. : P
Олексій А.

1
Чи є якісь обмеження щодо кольору виводу?
Matteo Italia

1
@ MartinBüttner: ніколи не знаю, я знайшов більш чистий спосіб; скажімо, що моя попередня ідея оббрила б байт, залишаючи всі закриті дужки, що блимають блакитним кольором ... :-)
Matteo Italia

8
@MatteoItalia о боже, я радий, що цього не сталося. ;)
Мартін Ендер

12
@MatteoItalia: Опублікуйте цю версію! Варто подивитися.
user2357112

Відповіді:


8

CJam, 17 16 15 байт

0000000: 72 3a 69 22 28 0b 20 9b 41 29 22 53 2f 66 3d     r:i"(. .A)"S/f=

Вищезазначене є оборотним дампами xxd, оскільки вихідний код містить недруковані символи VT (0x0b) та CSI (0x9b).

Як і у цій відповіді , він використовує послідовності відбору ANSI , але він також використовує вертикальні вкладки і друкує контрольні символи безпосередньо, щоб уникнути використання printf .

Для цього потрібний підтримуючий відеотекстовий термінал, який включає більшість емуляторів терміналів, що не є Windows.

Тестовий запуск

Ми повинні встановити змінну оболонки LANG і кодування емулятора термінала в ISO 8859-1. Перше досягається виконанням

$ LANGsave="$LANG"
$ LANG=en_US

Також перед тим, як виконати фактичний код, ми відключимо підказку та очистимо екран.

$ PS1save="$PS1"
$ unset PS1
$ clear

Це гарантує правильний показ результатів.

echo -n '()(())((()))(())()' | cjam <(base64 -d <<< cjppIigLIJtBKSJTL2Y9)
()(  )(    )(  )()
   ()  (  )  ()
        ()

Щоб відновити LANG та підказку, виконайте це:

$ LANG="$LANGsave"
$ PS1="$PS1save"

Як це працює

Вставляємо вертикальну вкладку після кожної ( для переміщення курсору вниз та послідовності байтів 9b 41 ( "\x9bA") перед кожним ) для переміщення курсору вгору.

r         e# Read a whitespace-separated token from STDIN.
:i        e# Replace each character by its code point.
          e#   '(' -> 40, ')' -> 41
"(. .A)"  e# Push the string "(\v \x9bA)".
S/        e# Split at spaces into ["(\v" "\x9bA)"].
f=        e# Select the corresponding chunks.
          e# Since arrays wrap around in CJam, ["(\v" "\x9bA)"]40= and 
          e# ["(\v" "\x9bA)"]41= select the first and second chunk, respectively.

49

машинний код x86, 39 34 33 30 29 байт

00000000  68 c3 b8 07 31 ff be 82  00 b3 a0 ad 4e 3c 28 7c  |h...1.......N<(||
00000010  f0 77 05 ab 01 df eb f3  29 df ab eb ee           |.w......)....|
0000001d

x86 збірка для DOS, з деякими хитрощами:

    org 100h

section .text

start:
    ; point the segment ES to video memory
    ; (c3 is chosen so that it doubles as a "ret")
    push 0b8c3h
    pop es
    ; di: output pointer to video memory
    xor di,di
    ; si: input pointer from the command line
    mov si,82h
    ; one row=160 bytes (assume bh=0, as should be)
    mov bl,160
lop:
    ; read & increment si (assume direction flag clean)
    ; we read a whole word, so that later we have something nonzero to
    ; put into character attributes
    lodsw
    ; we read 2 bytes, go back 1
    dec si
    ; check what we read
    cmp al,'('
    ; less than `(`: we got the final `\n` - quit
    ; (we jump mid-instruction to get a c3 i.e. a ret)
    jl start+1
    ; more than `(`: assume we got a `)`
    ja closed
    ; write a whole word (char+attrs), so we end
    ; one position on the right
    stosw
    ; move down
    add di,bx
    ; rinse & repeat
    jmp lop
closed:
    ; move up
    sub di,bx
    ; as above
    stosw
    jmp lop

Обмеження :

  • він завжди друкується починаючи внизу екрана, не стерши спочатку; a clsперед бігом майже обов’язковий;
  • кольори некрасиві; ось наслідком переробки наступного символу як кольорових атрибутів, щоб зберегти два байти тут і там;
  • код передбачає, bh=0а прапор напрямку чіткий на початку, як недокументований; OTOH, bxявно встановлено нуль у всіх варіантах DOS, які я бачив (DosBox, MS-DOS 2, FreeDOS), і скрізь, коли я тестував, прапори вже були в порядку.

введіть тут опис зображення


Щойно це підтвердили. Так, це працює. Ви впевнені, що вам потрібно зробити cld?
FUZxxl

@FUZxxl: на DosBox він працює чудово навіть без нього, але, дивлячись на його джерела, він говорить, що прапори збереглися від того, що сталося в DOS і в TRS, тому, ймовірно, потрібно було б його захистити. Так чи інакше, це був би лише один байт, справжньою виплатою було б вбити хоча б один із тих великих (= 4 байти кожен) add/ sub.
Маттео Італія

Гм ... ідея, насправді.
FUZxxl

Ви можете змінити , lopщоб loop?
mbomb007

@ mbomb007: можливо? Я не впевнений, чи не nasmрозрізняє loopяк етикетку та loopінструкцію по збірці, тому я просто пишу так, lopяк це роблять всі інші.
Маттео Італія

28

J, 32 28 байт

Це було весело.

0|:')(('&(i.-<:@+/\@i:){."0]

Пояснення

Ось як працює це рішення, включаючи пояснення того, як воно займалося гольфу.

   NB. Let a be a test case
   a =. '((()())()(()(())()))'

   NB. level alterations
   _1 + ').(' i. a
1 1 1 _1 1 _1 _1 1 _1 1 1 _1 1 1 _1 _1 1 _1 _1 _1

   NB. absolute levels
   +/\ _1 + ').(' i. a
1 2 3 2 3 2 1 2 1 2 3 2 3 4 3 2 3 2 1 0

   NB. adjusted levels
   (+/\ _1 + ').(' i. a) - ')(' i. a
0 1 2 2 2 2 1 1 1 1 2 2 2 3 3 2 2 2 1 0

   NB. take level from end of each item of a and transpose
   |: a {."0~ _1 - (+/\ _1 + ').(' i. a) - ')(' i. a
(                  )
 (    )()(        ) 
  ()()    ()(  )()  
             ()     

   NB. code as a tacit verb
   [: |: ] {."0~ _1 - ([: +/\ _1 + ').(' i. ]) - ')(' i. ]

   NB. subtractions pulled into the prefix insert
   [: |: ] {."0~ (')(' i. ]) - [: <:@+/\ ').(' i. ]

   NB. i: instead of i. so we can use the same string constant
   [: |: ] {."0~ (')((' i. ]) - [: <:@+/\ ')((' i: ]

   NB. get rid of the caps
   0 |: ] {."0~ (')((' i. ]) - ')((' <:@+/\@i: ]

   NB. join the two usages of ')((' into a single dyadic phrase
   0 |: ] {."0~ ')((' (i. - <:@+/\@i:) ]

   NB. bond ')((' and flip arguments to {."0
   0 |: ')(('&(i. - <:@+/\@i:) {."0 ]

1
Дуже хороша! Рішення сповнене чудових частин!
randomra

1
(Я зазвичай додаю приклад виклику функції, щоб не досвідчені користувачі могли також спробувати її.)
randomra

Це рішення змушує мене боліти голова:')
Нік Хартлі

@QPaysTaxes Я сприймаю це як комплімент.
FUZxxl

@FUZxxl Це так. Це також каламбур, заснований на послідовності символів, яка з’являється у вашій відповіді.
Нік Хартлі

15

C, 150 байт

t;f(char*c){char l=strlen(c)+1,o[l*l],*A=o,m=0;for(t=1;t<l*l;t++)o[t-1]=t%l?32:10;for(t=-1;*c;c++)A++[l*(*c-41?++t>m?m=t:t:t--)]=*c;A[m*l]=0;puts(o);}

Це була божевільна забава для гольфу. Я досі не впевнений, що з цим закінчую.

Ми визначимо єдину функцію, fяка приймає рядок як вхідний і вихідний для stdout.

Давайте переглянемо код, рядок за рядком:

/* t will represent the current depth of a parentheses. It must be an int. */
t;
f(char*c){
    //Our variables:
    char l=strlen(c)+1,    //The length of each row of output, including newlines
         o[l*l],           //The output string. It's way larger than it needs to be.
         *A=o,             //We need another pointer to keep track of things.
         m=0;              //The maximum depth recorded thus far.

    for(t=1;t<l*l;t++)     //For each character in our output...
        o[t-1]=t%l?32:10;  //If it's at the end of a line, make it '\n'. Else, ' '.
    for(t=-1;*c;c++)       //While we have an input string...
        //Perhaps a personal record for ugliest warning-less line...
        A++[l*(*c-41?++t>m?m=t:t:t--)]=*c;
    /* 
        A breakdown:
        A++        --> Go to the next *column* of output, after writing. 
                   --> There will only ever be one parentheses per output column.
        [l*(...)]  --> A[l*X] is the character in the current column at depth X.
        (*c-41?    --> If the character is a '('...    
        ++t>m?     --> Increment t *before* we write it. If this is a new highest depth
        m=t:       --> Set m to t, and set the whole expression to t.
        t:         --> If it's not a new highest depth, don't set m.
        t--)       --> If the character was a ')', decrement t *after* we write it.
        =*c        --> Write our output character to whatever the input read.
    */    

    A[m*l]=0; //The last character of the maximum-depth line should be null terminated.
    puts(o);  //Output!
}

Я відповім на будь-які питання, які у вас є!

Спробуйте програму тестування онлайн !


Хочу пам'ятати, що "char l = strlen (c) +1, o [l * l]" не вірно, тому що ви не можете визначити масив змінних розмірів так, але минуло 15 років, як я намагався щось із що в C.
Sparr

@Sparr Мій компілятор навіть не кидає попередження. Я вважаю, що це було "офіційно" стандартом у C99. Я спробую знайти довідку для цього.
BrainSteel

1
@Sparr Ось посилання.
BrainSteel

Дякую. Здається, у цьому відношенні все змінилося близько 15 (дайте або візьміть пару) років тому
Sparr

1
@CoolGuy Це, але після наступних дзвінків f, mне буде скинуто до 0. Це вважається "порушенням вашого середовища", забороненим тут .
BrainSteel

15

Сітківка + Bash, 27 байт (14 + 10 + 3 = 27)

Для цього використовується ANSI Escapes:

\(
(\e[B
\)
\e[A)

Еквівалентно sed -e "s/(/(\\\e[B/g;s/)/\\\e[A)/g". Код \e[Bбігу означає переміщення курсору вниз на один рядок, а \e[Aзасіб переміщення курсору вгору на один рядок, тому це рішення просто вставляє ці коди після і перед початком і кінцем кожної вкладеної пари дужок. Вхід передається через STDIN.

Вам доведеться викликати його, printf $(Retina ...)щоб правильно бачити вихід.

Вихідні дані

(((())))
(\e[B(\e[B(\e[B(\e[B\e[A)\e[A)\e[A)\e[A)
^C
amans:~ a$ printf "(\e[B(\e[B(\e[B(\e[B\e[A)\e[A)\e[A)\e[A)"
(      )amans:~ a$ 
 (    )
  (  )
   ()

((()())()(()(())()))
(\e[B(\e[B(\e[B\e[A)(\e[B\e[A)\e[A)(\e[B\e[A)(\e[B(\e[B\e[A)(\e[B(\e[B\e[A)\e[A)(\e[B\e[A)\e[A)\e[A)
^C
amans:~ a$ printf "(\e[B(\e[B(\e[B\e[A)(\e[B\e[A)\e[A)(\e[B\e[A)(\e[B(\e[B\e[A)(\e[B(\e[B\e[A)\e[A)(\e[B\e[A)\e[A)\e[A)"
(                  )amans:~ a$ 
 (    )()(        )
  ()()    ()(  )()
             ()

1
Ну, непогано! Якби ви могли вказати на конкретний термінал, який не потребує, printfце було б чудово. В іншому випадку, я думаю, було б справедливо лише додати | printfкількість байтів.
Мартін Ендер

@ MartinBüttner Це повинно бути printf $()або printf $(Retina ).
jimmy23013

1
Що це за Retina?
FUZxxl

2
@FUZxxl Це моя власна мова програмування на основі регулярних виразів. Дивіться GitHub .
Мартін Ендер

2
Чому \eплюс printf? Ви можете просто поставити контрольні символи в шаблон заміни.
Денніс

15

TI-BASIC, 69 60 56 55 байт

Це для калькуляторів сімейства TI-83 + / 84 +, хоча це було написано на срібній версії 84+.

Програма відображається як збільшена плата за рахунок включеної інформації про ПДВ + розмір. Також тут є понад 56 символів; причина 56 байт - це те, що всі команди, що містять більше одного символу, стискаються до лексем, розміром яких є один або два байти.

Input Str1
1→B
For(A,1,length(Str1
sub(Str1,A,1→Str2
Ans="(
Output(B+Ans,A,Str2
B-1+2Ans→B
End

Поголив ще один байт завдяки томасу-ква ! (також від нього був стрибок з 60 до 56.)


4
А-а-а, моя перша мова програмування. Дякую за ностальгію, ха-ха.
Олексій Причард

1
Ще програмуючи TI для середнього класу з математики, дуже корисно мати вбудовані формули, які підрахують для вас тести та завдання.
Elias Benevedes

1
Якщо ви зміните речі навколо, ви можете скористатися cos(piAnsтрюком, щоб зберегти ще один байт.
ліртосіаст

9

Python 2, 115 байт

def f(L,n=0,O=()):
 for c in L:n-=c>"(";O+=" "*n+c,;n+=c<")"
 for r in map(None,*O):print"".join(c or" "for c in r)

Дзвінок як f("((()())()(()(())()))"), і вихід для STDOUT.

Пояснення

Почнемо з n = 0. Для кожного знака в рядку введення:

  • Якщо знак char (, ми додаємо nпробіли, а потім прирістn
  • Якщо знак char ), ми декрементуємо, nтоді додаємо nпробіли

Потім результат відскакується та роздруковується. Зауважте, що zipблискавки Python відповідають довжині найкоротшого елемента, наприклад

>>> zip([1, 2], [3, 4], [5, 6, 7])
[(1, 3, 5), (2, 4, 6)]

Зазвичай можна використовувати itertools.zip_longest( izip_longest), якби вони хотіли zipпрокладати довжину найдовшого елемента.

>>> import itertools
>>> list(itertools.izip_longest([1, 2], [3, 4], [5, 6, 7]))
[(1, 3, 5), (2, 4, 6), (None, None, 7)]

Але в Python 2 таку поведінку можна змоделювати за допомогою відображення None:

>>> map(None, [1, 2], [3, 4], [5, 6, 7])
[(1, 3, 5), (2, 4, 6), (None, None, 7)]

Python 3, 115 байт

L,d,*O=input(),0
for i,c in enumerate(L):b=c>"(";O+="",;O[d-b]=O[d-b].ljust(i)+c;d-=b*2-1
for l in O:l and print(l)

Ніяких блискавок, просто підкладка належним чином ljust. Цей, здається, має певний потенціал для гольфу.


8

R, 151 127 символів

S=strsplit(scan(,""),"")[[1]];C=cumsum;D=c(C(S=="("),0)-c(0,C(S==")"));for(j in 1:max(D)){X=S;X[D!=j]=' ';cat(X,sep='',fill=T)}

З відступами та новими рядками:

S=strsplit(scan(,""),"")[[1]]
C=cumsum
D=c(C(S=="("),0)-c(0,C(S==")"))
for(j in 1:max(D)){
    X=S
    X[D!=j]=' '
    cat(X,sep='',fill=T)
    }

Використання:

> S=strsplit(scan(,""),"")[[1]];C=cumsum;D=c(C(S=="("),0)-c(0,C(S==")"));for(j in 1:max(D)){X=S;X[D!=j]=' ';cat(X,sep='',fill=T)}
1: ()(())((()))(())()
2: 
Read 1 item
()(  )(    )(  )()
   ()  (  )  ()   
        ()        
> S=strsplit(scan(,""),"")[[1]];C=cumsum;D=c(C(S=="("),0)-c(0,C(S==")"));for(j in 1:max(D)){X=S;X[D!=j]=' ';cat(X,sep='',fill=T)}
1: ((()())()(()(())()))
2: 
Read 1 item
(                  )
 (    )()(        ) 
  ()()    ()(  )()  
             ()     

Він читає рядок як stdin, розбиває його як вектор одиничних символів, обчислює сукупну суму (та ), піддає першому з останнім (з відставанням), таким чином обчислюючи "рівень" кожної дужки. Потім він друкує для stdout для кожного рівня або відповідні дужки, або пробіл.

Дякуємо @MickyT за те, що він допомагав мені значно скоротити його!


2
+1 Приємне та елегантне рішення. 6 можна зберегти, замінивши for(i in n)cat(ifelse(D[i]-j," ",S[i]));cat("\n")на X=S;X[which(D!=j)]=' ';cat(X,sep='',fill=T). Тоді nнасправді не потрібно, але вам знадобиться трохи змінити дипломну частину. D=c(C(S=="("),0)-c(0,C(S==")"));знизивши його до 135.
MickyT

@MickyT дякую! не думав про це. whichТут насправді не потрібно ( D!=jбудучи вже булевим вектором, що дозволяє індексувати). Я не знаю , аргумент fillдля cat, це відмінний трюк! Дякую за те, що змусив мене скоротити його дивними 24 символами !!
планнапус

8

C, 58 53 52 51 49 байт

Використовує послідовності втечі ANSI для переміщення положення курсору.

f(char*s){while(*s)printf(*s++&1?"\e[A)":"(\v");}

Якщо не використовується gcc або інший компілятор, який підтримує, \eто його можна замінити \x1Bна 2 додаткові байти. \e[Aпереміщує курсор вгору на один рядок і \e[Bпереміщує курсор вниз на один рядок. Не потрібно використовувати \e[Bдля переміщення вниз по одному рядку, оскільки на два байти коротше використовувати символ вертикальної вкладки ASCII 0xBабо \v.

Вхідний рядок передбачається, що з питання, складається з лише (врівноважених) дужок, тому для перевірки парності символів, з &1, достатньо, щоб розрізняти (і ).


7

Піп, 53 байти

Піп - мова кодового гольфу мого винаходу. Перша версія була опублікована в суботу, тому я можу офіційно взяти її за спін! Наведене нижче рішення не є надзвичайно конкурентоспроможним, оскільки мови для гольфу є, але це частково тому, що я ще не реалізував такі речі, як zip та max.

z:{aEQ'(?++v--v+1}MaW(o:{z@++v=i?as}Ma)RMs{Pov:-1++i}

Очікує рядок дужок як аргумент командного рядка.

Версія "Unololfed":

z:{
   a EQ '( ?
    ++v
    --v+1
  } M a
W (o:{
      z @ ++v = i ?
       a
       s
     } M a
  ) RM s
{
 P o
 v:-1
 ++i
}

Пояснення:

На відміну від більшості мов для гольфу, Pip необхідний для операторів інфікування, тому синтаксис дещо наближений до C та його похідних. Він також запозичує ідеї з функціонального та на основі масиву програмування. Щоб отримати подальшу документацію, перегляньте сховище.

Програма спочатку генерує перелік глибин (зберігає їх у z) шляхом зіставлення функції у вхідний рядок a. Глобальна змінна vвідстежує поточний рівень. (Змінні a-gв Pip - це локальні функціональні змінні, але h-zє глобальними. vЦе зручно, оскільки він попередньо ініціалізований до -1.)

Далі ми використовуємо Wцикл hile для генерації та друку кожного рядка, поки згенерований рядок не буде складатися з усіх пробілів. vзараз використовується як для стовпців, так і iдля рядків. {z@++v=i?as}Функція, неодноразово зіставляється з вихідної вхідного рядка, перевіряє , є чи поточна рядок iзбігу лінії струму дужка повинна бути (як зберігається в zсписку). Якщо так, використовуйте круглі дужки ( a); якщо ні, використовуйте s(попередньо виділений у космос). Кінцевим результатом є те, що на кожній ітерації oприсвоюється список символів, еквівалентний наступному рядку виводу.

Щоб перевірити, чи слід продовжувати циклічно, ми перевіряємо, чи oвсі пробіли RMпорожні. Якщо ні, роздрукуйте його (що за замовчуванням об'єднує все разом, як у CJam), скиньте номер стовпця до -1 та збільште номер рядка.

(Факт забави: Спочатку у мене було 51-байтове рішення ... яке не спрацювало, оскільки виявилася помилка в інтерпретаторі.)


7

Pyth, 31 байт

VzJs.e?YqN-/<zk\(/<zhk\)dzI-JdJ

Спробуйте в Інтернеті.

-/<zk\(/<zhk\): Знаходить відповідний рівень для поточної позиції символу.

?YqN-/<zk\(/<zhk\)d: Пробіл, якщо відповідний рівень не є поточним рівнем, поточний символ в іншому випадку.

Js.e?YqN-/<zk\(/<zhk\)dz: Створіть рядок, збережіть його в J.

I-JdJ: Якщо Jце не всі пробіли, роздрукуйте їх.

Vz: zЧаси циклу .


6

GNU Bash + coreutils + відступ, 135

eval paste "`tr '()' {}|indent -nut -i1 -nbap|sed 's/.*/<(fold -1<<<"&")/'|tr '
' \ `"|expand -t2|sed 'y/{}/()/;s/\(.\) /\1/g;s/ \+$//'

Вхід / вихід через STDIN / STDOUT:

$ ./telescopic.sh <<< "(()(()())()((())))(())"
(                )(  )
 ()(    )()(    )  ()
    ()()    (  )
             ()
$ 

indentробить більшу частину важкого підйому, але йому потрібно працювати з брекетами замість парен. Решта - це модифікація цієї відповіді для транспонування результату indent.


5

Пітон 2, 92

def f(s,i=0,z=''):
 for x in s:b=x>'(';z+=[' ',x][i==b];i-=2*b-1
 if'('in z:print z;f(s,i-1)

Друкується рядок за рядком. Для заданого номера рядка i(власне його заперечення) проходить через вхідний рядок sі створює новий рядок, zякий містить лише символи sна глибину i. Це робиться шляхом збільшення або декрементації iдля відстеження поточної глибини, а також додавання поточних символів, коли iце 0налаштовано на тип батьків, та іншим чином додавання пробілу.

Потім друкується та повторюється наступний, iякщо у поточному рядку не було пробілів. Зауважте, що оскільки паролі врівноважені, iцикл після циклу такий же, як і на початку.

Python 3 був би таким же, за винятком символу для print(z).


5

обман :( Retina + TeX, N байт обману :(

Це працює лише в тому випадку, якщо ви надаєте (?) Вихід за допомогою MathJax або якогось іншого TeX, який наразі вимкнено для цього SE :(

\(
({
\)
})
\{\(
_{(

Кожен рядок повинен бути в іншому файлі, але ви можете протестувати його, використовуючи Retina -e "\(" -e "({" -e "\)" -e "})" -e "\{\(" -e "_{("(або еквівалентну команду sed sed -e "s/(/({/g;s/)/})/g;s/{(/_{(/g"). Вхід передається через STDIN.

Це працює, додаючи вміст кожної пари круглих дужок у дужки, а потім підписавши всі елементи всередині них.

Вихідні дані

(((())))
(_{(_{(_{({})})})})

()(())((()))(())()
({})(_{({})})(_{(_{({})})})(_{({})})({})

((()())()(()(())()))
(_{(_{({})({})})({})(_{({})(_{({})})({})})})

Вихід TeX


1
Мені приємно, що ви використовували Retina, і це приємно мислити поза межами коробки, але це не зовсім так, як повинен виглядати вихід. ;) Зокрема, це порушує альтернативну формулювання "Ще один спосіб дивитися на це - дужки на глибині n переміщуються до рядка n, зберігаючи їх горизонтальне положення". Я був би дуже вражений чистим рішенням Retina, що відповідає правилам, і, можливо, може подарувати щедро. ;)
Мартін Ендер

In total the lines must not be longer than twice the length of the input string. Зміна рядків 2 на (\,{4 та рядка }\,)означає, що вихід відповідає цьому (хоча вертикальна глибина все ще неправильна: ()
user22723

Ну, мені вдалося прийняти рішення, сумісне з правилами
:)

1
Хороша робота. Я думаю, це означає, що ви можете видалити хитру відповідь зараз. ;)
Мартін Ендер

5

Java, 232 226 224 222 байти

Версія для гольфу:

int i,j,k,l,m,a[];void f(String s){a=new int[s.length()];j=a.length;for(k=0;k<j;){a[k]=s.charAt(k++)<41?i++:--i;m=m<i?i:m;}for(k=0;k<m;k++)for(l=0;l<j;)System.out.print(k==a[l++]?i++%2<1?'(':l==j?")\n":')':l==j?'\n':' ');}

Довга версія:

int i, j, k, l, m, a[];
void f(String s) {
    a = new int[s.length()];
    j = a.length;
    for (k = 0; k < j;) {
        a[k] = s.charAt(k++) < 41 ? i++ : --i;
        m = m < i ? i : m;
    }
    for (k = 0; k < m; k++)
        for (l = 0; l < j;)
            System.out.print(k == a[l++] ? (i++ % 2 < 1 ? '(' : (l == j ? ")\n" : ')')) : (l == j ? '\n':' '));
}

Спочатку аналізується рядок введення, шукаючи "(" і ")", щоб додати / відняти лічильник і зберегти його значення, визначаючи, наскільки далеко в дужках має пройти масив, а також слідкуючи, наскільки глибоко йде найглибше. Потім аналізується масив; круглі дужки з меншими значеннями надрукуються спочатку, і вони продовжуватимуть друкувати рядок за рядком, поки не буде досягнуто максимуму.

Я, мабуть, знайду шляхи для гольфу далі пізніше.


5

Javascript / ES6, 97 символів

f=s=>{for(n in s){m=o=d='';for(c of s)o+=n==(c<')'?d++:--d)?c:' ',m=m<d?d:m;n<m&&console.log(o)}}

Використання

f("(()(()())()((())))(())")

Пояснення

fn=str=>{                          // accepts string of parenthesis
  for(line in str){                // repeat process n times where n = str.length
    max=output=depth='';           // max: max depth, output: what to print, depth: current depth
    for(char of str)               // iterate over chars of str
      output+=
        line==(char<')'?depth++:--depth)? // update depth, if line is equal to current depth
        char:' ',                  // append either '(', ')', or ' '
        max=max<depth?depth:max;   // update max depth
    line<max&&console.log(output)  // print if current line is less than max depth
  }
}

Замість цього n<m?console.log(o):0ви можете використовувати, n<m&&console.log(o)який зберігає 1 байт.
Ісмаїл Мігель

4

CJam, 43 41 36 байт

Не надто гольф (я думаю), але ось моя перша спроба:

l:L,{)L<)_')=@~zS*\+}%_$0=,f{Se]}zN*

Як це працює

Я використовую дуже зручний факт, що )і (в CJam означають приріст і декремент відповідно. Таким чином, я просто оцінюю дужки, щоб отримати глибину.

l:L,{)L<)_')=@~zS*\+}%_$0=,f{Se]}zN*
l:L,{                    }%                "Store input line in L and iterate over [0,L)";
     )L<                                   "substr(L, 0, iterator + 1)";
        )                                  "Slice off the last character to stack";
         _')=                              "Put 0 on stack if the sliced character is (,
                                            else 1 if sliced character is )";
             @~                            "bring forth the remaining
                                            brackets after slicing and evaluate them";
               zS*                         "Stack has negative depth number, take absolute
                                            value and get that many spaces";
                  \+                       "Prepend to the sliced character";
                      _$0=,                "Get the maximum depth of brackets";
                           f{Se]}          "Pad enough spaces after each string to match
                                            the length of each part";
                                 zN*       "Transpose and join with new lines";

Спробуйте його онлайн тут


4

Октава, 85 символів

function r=p(s)i=j=0;for b=s k=b==40;k&&++j;t(j,++i)=9-k;k||--j;r=char(t+32);end;end

Це оптимізація наївного підходу, що насправді є досить природним для Matlab та Octave:

function r=p(s)
i=j=1;
for b=s
 if b=='(' t(++j,i++)='(' else t(j--,i++)=')' end; end; t(~t)=' '; r=char(t);
end;

Таблиця, t можливо, ще не існує, і ми можемо призначити будь-який елемент відразу, і він перетворюється на найменший розмір, необхідний для існування цього елемента, що є досить зручним.


4

Perl, 91 89 88 84 80 79 байт

$t=<>;{$_=$t;s/\((?{$l++})|.(?{--$l})/$^R==$c?$&:$"/ge;print,++$c,redo if/\S/}
  • $ t - рядок введення.
  • $ c - глибина, яку ми хочемо надрукувати на поточному рядку.
  • $ l - глибина, на якій ми знаходимося після зустрічі з батьком.
  • $ l оновлюється у кодах, вбудованих у регулярні коди .
  • $ ^ R - результат останнього блоку коду.

4

Haskell, 154 байти

f h('(':s)=h:f(h+1)s;f h(')':s)=(h-1):f(h-1)s;f _ _=[]
main=interact$ \s->unlines[[if i==h then c else ' '|(c,i)<-zip s l]|let l=f 0 s,h<-[0..maximum l]]

та ж ідея, що й інше рішення Haskell, але дещо коротша. - Використання:

echo  '(((())())(()))' | runghc Golf.hs

3

J, 46

Не настільки чудово, як інші "мови для гольфу", але на мій захист: J жахливий зі струнами.

[:|:(((,~(' '#~]))"0)(0,2%~[:+/\2+/\1-'(('i.]))~

Приймає рядок як вхід для функції. Можливо, є й кращий спосіб зробити це в Дж.

Використання:

   f=:[:|:(((,~(' '#~]))"0)(0,2%~[:+/\2+/\1-'(('i.]))~
   f '(()(()())()((())))(())'
(                )(  )
 ()(    )()(    )  () 
    ()()    (  )      
             ()       

Дивіться мою відповідь щодо іншого способу цього в Дж.
FUZxxl

3
Особисто я вважаю, що J ідеально підходить для струн. Потрібно просто подумати з масивами.
FUZxxl

3

Рубі, 119 115 114

->s{r=[""]*s.size
d=0
s.chars.map{|l|r.map!{|s|s+" "}
b=l>"("?1:0
d-=b
r[d][-1]=l
d+=1-b}.max.times{|i|puts r[i]}}

Пояснення:

->s{r=[""]*s.size  # Take an array of strings big enough
d=0                # This will contain the current depth
s.chars.map{|l|r.map!{|s|s+" "}  # Add a new space to every array
b=l>"("?1:0       # Inc/Dec value of the depth
d-=b               # Decrement depth if we are at a closing paren
r[d][-1]=l         # Set the corresponding space to the actual open/close paren
d+=1-b             # Increment the depth if we are at a opening paren
}.max.times{|i|puts r[i]}}  # Print only the lines up to the max depth

3

Java, 233 214 байт

void f(String s){int p,x,d,l=s.length();char c,m[]=new char[l*l];java.util.Arrays.fill(m,' ');p=x=0;while(x<l){d=(c=s.charAt(x))==40?p++:--p;m[d*l+x++]=c;}for(x=0;x<l*l;x++)System.out.print((x%l==0?"\n":"")+m[x]);}

Відступ:

void f(String s){
    int p, x, d, l = s.length();
    char c, m[] = new char[l * l];
    java.util.Arrays.fill(m, ' ');
    p = x = 0;
    while (x < l){
        d = (c = s.charAt(x)) == 40
                ? p++
                : --p;
        m[d * l + x++] = c;
    }
    for (x = 0; x < l * l; x++)
        System.out.print((x % l == 0 ? "\n" : "") + m[x]);
}

Думаю, остаточний цикл можна було б скоротити, але я залишу це як вправу для читача. ;-)


Старий, 233 байти відповідь:

void f(String s){int y=s.length(),x=0;char[][]m=new char[y][y];for(char[]q:m)java.util.Arrays.fill(q,' ');y=0;for(char c:s.toCharArray())if(c=='(')m[y++][x++]=c;else m[--y][x++]=c;for(char[]q:m)System.out.println(String.valueOf(q));}

Відступ:

static void f(String s) {
    int y = s.length(), x = 0;
    char[][] m = new char[y][y];
    for(char[] q : m)
        java.util.Arrays.fill(q, ' ');
    y = 0;
    for(char c : s.toCharArray())
        if(c == '(')
            m[y++][x++] = c;
        else
            m[--y][x++] = c;
    for(char[] q : m)
        System.out.println(String.valueOf(q));
}

Я знаю, що минуло більше року, але "я думаю, остаточний цикл можна було б скоротити, але я залишу це як вправу для читача. ;-)"; ти справді правий. Його можна змінити з for(x=0;x<l*l;x++)System.out.print((x%l==0?"\n":"")+m[x]);на for(x=0;x<l*l;)System.out.print((x%l==0?"\n":"")+m[x++]);-1 байт. Крім того, ви можете зберегти ще 2 байти, видаливши p=x=0і int p=0,x=0,замість цього просто скориставшись ініціалізацією полів. Всього це стає 211 байт .
Kevin Cruijssen

3

C #, 195 байт

Спочатку спробуйте в гольф - кричите, якщо я щось зробив не так.

Альтернативна версія C #, що використовує SetCursorPosition та працює зліва направо, приймаючи вхід як аргумент командного рядка.

using System;class P{static void Main(string[] a){Action<int,int>p=Console.SetCursorPosition;int r=0,c=0;foreach(var x in a[0]){r+=x==')'?-1:0;p(c,r);Console.Write(x);r+=x=='('?1:0;p(c,r);c++;}}}

Я подумав, що було б цікаво регулювати положення запису на основі батьківського відкритого / закритого, а не повних рядків. Близький батьків рухає положення вгору перед написанням; відкритий батьків пересуває його після написання. Дія SetCursorPosition економить п'ять байтів. Переміщення курсору на наступний рядок після виходу буде зайвим трохи зайвим.

using System;
class P
{
    static void Main(string[] a)
    {
        Action<int, int> p = Console.SetCursorPosition;
        int r = 0, c = 0;
        foreach (var x in a[0])
        {            
            r += x == ')' ? -1 : 0;
            p(c, r);
            Console.Write(x);
            r += x == '(' ? 1 : 0;
            p(c, r);
            c++;
        }
    }
}

3

Пакетна, 356 335 байт

Я знаю, що вже існує пакетне рішення для цього виклику, але цей гольф значно більший і, схоже, застосовує інший підхід. Найголовніше, що інше пакетне рішення містить щонайменше одну команду shellhell; це рішення не робить.

@echo off
setlocal enabledelayedexpansion
set p=%1
set p=%p:(="(",%
set p=%p:)=")",%
set c=0
for %%a in (%p%)do (if ")"==%%a set/ac-=1
set d=!d!,!c!%%~a
if "("==%%a set/ac+=1&if !c! GTR !m! set m=!c!)
set/am-=1
for /l %%a in (0,1,!m!)do (for %%b in (!d!)do (set t=%%b
if "%%a"=="!t:~0,-1!" (cd|set/p=!t:~-1!)else (cd|set/p=. ))
echo.)

На U+0008другому та останньому рядку слідом за крапкою є символ зворотної області ( ) (рядок 12, стовпець 57). Це не видно в коді, розміщеному тут, але включений у кількість байтів.


Хтось ще насправді подав відповідь у пакетній групі - Приємно один +1.
нечисте м'ясо

3

Пакетна, 424 байт

@echo off
setLocal enableDelayedExpansion
set s=%1
set a=1
:c
if defined s (set/ac+=1
set "z="
if "%s:~0,1%"=="(" (set "1=(")else (set/aa-=1
set "1=)")
for %%a in (!a!)do for /f usebackq %%b in (`powershell "'!l%%a!'".Length`)do (set/ay=!c!-%%b
for /l %%a in (1,1,!y!)do set z= !z!
set "l%%a=!l%%a!!z!!1!")
if "%s:~0,1%"=="(" set/aa+=1
if !a! GTR !l! set/al=!a!-1
set "s=%s:~1%"
goto c)
for /l %%a in (1,1,!l!)do echo !l%%a!

Без гольфу:

@echo off
setLocal enableDelayedExpansion

set s=%1
set a=1
set c=0
set l=0

:c
if defined s (
    set /a c+=1
    set "z="
    if "%s:~0,1%"=="(" (
        set "1=("
    ) else (
        set /a a-=1
        set "1=)"
    )
    for %%a in (!a!) do for /f usebackq %%b in (`powershell "'!l%%a!'".Length`) do (
        set /a y=!c!-%%b
        for /l %%a in (1,1,!y!) do set z= !z!
        set "l%%a=!l%%a!!z!!1!"
    )
    if "%s:~0,1%"=="(" set /a a+=1
    if !a! GTR !l! set /a l=!a!-1
    set "s=%s:~1%"
    goto c
)

for /l %%a in (1,1,!l!) do echo !l%%a!

Приклад:

h:\>par.bat (((())())(()))
 (            )
  (      )(  )
   (  )()  ()
    ()

3

C, 118 117 байт

Ще одна відповідь на С, але моя коротша.

c;d;main(m,v)int**v;{while(d++<m){char*p=v[1];while(*p)c+=*p==40,putchar(c-d?*p:32),m=c>m?c:m,c-=*p++==41;puts("");}}

Негольована версія:

c; /* current depth */
d; /* depth to print in current row */
main(m,v)int**v;{
    while(d++<m) {
        char*p=v[1];
        while(*p){
            c+=*p==40;           /* 40 = '(' */
            putchar(c-d?*p:32); /* 32 = ' ' (space) */
            m=c>m?c:m;           /* search maximum depth */
            c-=*p++==41;         /* 41 = ')' */
        }
        puts("");
    }
}

І це працює!

% ./telescope '()(())((()))(())()'
()(  )(    )(  )()
   ()  (  )  ()
        ()
% ./telescope '((()())()(()(())()))'
(                  )
 (    )()(        )
  ()()    ()(  )()
             ()

1
Досить елегантне рішення, однак putchar(c-d?32:*p)на один символ коротше putchar(c==d?*p:32).
pawel.boczarski

2

Haskell, 227 байт

n _ []=[]
n h ('(':r)=('(',h):n(h+1)r
n d (')':r)=let h=d-1 in(')',h):n h r
m n []=n
m n ((_,h):r)=m(max h n)r
p s=let v=n 0 s;h=m 0 v;in map(\d->map(\(b,l)->if l==d then b else ' ')v)[0..h]
main=fmap p getLine>>=mapM_ putStrLn

1
Ви можете зберегти кілька пробілів за допомогою операторів: наприклад, n#[]замість m n [].
Френкі


2

Лекс, 94 байти

Залежить від кодів консолі Linux. За допомогою gcc ви можете вирізати чотири байти, замінивши обидва екземпляри \33фактичним символом втечі.

%%
 int p[2]={0};
\( printf("(\33D");++p[!*p];
\) printf("\33M)");--*p;
\n while(p[1]--)ECHO;

Для складання та запуску:

$ flex -o telescopic.c telescopic.l
$ gcc -o telecopic telescopic.c -lfl
$ ./telescopic
(()(()())()((())))(())
(                )(  )
 ()(    )()(    )  ()
    ()()    (  )
             ()
--- type ctrl-D ---
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.