Parênteses telescópicos


79

Considere uma sequência não vazia de parênteses corretamente balanceados:

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

Podemos imaginar que cada par de parênteses representa um anel em uma construção telescópica em colapso . Então, vamos estender o telescópio:

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

Outra maneira de ver isso é que os parênteses na profundidade n são movidos para a linha n , mantendo sua posição horizontal.

Sua tarefa é pegar uma série de parênteses equilibrados e produzir a versão estendida.

Você pode escrever um programa ou função, obtendo entrada via STDIN (ou equivalente mais próximo), argumento da linha de comando ou parâmetro de função e produzindo saída via STDOUT (ou equivalente mais próximo), valor de retorno ou parâmetro de função (saída).

Você pode assumir que a sequência de entrada é válida, ou seja, consiste apenas de parênteses, que estão corretamente equilibrados.

Você pode imprimir espaços à direita em cada linha, mas não mais espaços à esquerda do que o necessário. No total, as linhas não devem exceder o dobro do comprimento da sequência de entrada. Opcionalmente, você pode imprimir uma única nova linha à direita.

Exemplos

Além do exemplo acima, aqui estão mais alguns casos de teste (entrada e saída são separadas por uma linha vazia).

()

()
(((())))

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

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

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

Desafios relacionados:

  • Topographic Strings , que solicita que você produza o que é essencialmente o complemento da saída nesse desafio.
  • Code Explanation Formatter , uma ampla generalização das idéias nesse desafio, publicada recentemente pela PhiNotPi. (De fato, a descrição original de PhiNotPi de sua ideia foi o que inspirou esse desafio.)

Classificação

Huh, isso teve muita participação, então aqui está um snippet de pilha para gerar um placar regular e uma visão geral dos vencedores por idioma.

Para garantir que sua resposta seja exibida, inicie-a com um título, usando o seguinte modelo de remarcação:

# Language Name, N bytes

onde Nestá o tamanho do seu envio. Se você melhorar sua pontuação, poderá manter as pontuações antigas no título, identificando-as. Por exemplo:

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


17
Título alternativo: De-Lisp-ify uma string. : P
Alex A.

1
Existem restrições sobre a cor da saída?
Matteo Italia

1
@ MartinBüttner: deixa pra lá, encontrei uma maneira mais limpa; vamos apenas dizer que a minha ideia anterior teria raspado um byte deixando todos os parênteses fechados piscando azul sobre cyan ... :-)
Matteo Italia

8
@ MatteoItalia oh deus, estou feliz que isso não aconteceu. ;)
Martin Ender

12
@MatteoItalia: Publique essa versão! Vale a pena ver.
user2357112

Respostas:


8

CJam, 17 16 15 bytes

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

O acima é um despejo xxd reversível, pois o código-fonte contém os caracteres não imprimíveis VT (0x0b) e CSI (0x9b).

Como esta resposta , ele usa seqüências de escape ANSI , mas também usa guias verticais e imprime os caracteres de controle diretamente para evitar o uso de printf .

Isso requer um terminal de texto de vídeo de suporte, que inclui a maioria dos emuladores de terminal não Windows.

Execução de teste

Temos que definir a variável de shell LANG e a codificação do emulador de terminal para ISO 8859-1. O primeiro é alcançado executando

$ LANGsave="$LANG"
$ LANG=en_US

Além disso, antes de executar o código real, desativaremos o prompt e limparemos a tela.

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

Isso garante que a saída seja mostrada corretamente.

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

Para restaurar o LANG e o prompt, execute o seguinte:

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

Como funciona

Nós inserimos uma guia vertical após cada um ( para mover o cursor para baixo e a sequência de bytes 9b 41 ( "\x9bA") antes de cada ) para mover o cursor para cima.

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

código de máquina x86, 39. 34 33 30 29 bytes

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

montagem x86 para DOS, com alguns truques:

    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

Limitações :

  • sempre imprime começando na parte inferior da tela, sem apagar primeiro; a clsantes da execução é quase obrigatório;
  • as cores são feias; essa é a consequência de reciclar o próximo caractere como atributo de cor para salvar dois bytes aqui e ali;
  • o código assume bh=0e o sinalizador de direção é limpo no início, ambos não documentados; OTOH, bxé explicitamente definido como zero em todas as variantes do DOS que eu vi (DosBox, MS-DOS 2, FreeDOS) e em todos os lugares que testei, os sinalizadores já estavam OK.

insira a descrição da imagem aqui


Apenas verifiquei isso. Sim, funciona. Tem certeza de que precisa fazer cld?
FUZxxl

@FUZxxl: no DosBox, ele funciona bem mesmo sem ele, mas, olhando para suas fontes, diz que as bandeiras são preservadas do que aconteceu no DOS e nos TRSs antes, então provavelmente seria necessário jogar com segurança. De qualquer forma, isso seria apenas um byte, a verdadeira recompensa seria matar pelo menos um desses grandes (= 4 bytes cada) add/ sub.
Matteo Italia

Hum ... não faço ideia, realmente.
FUZxxl

Você pode mudar loppara loop?
mbomb007

@ mbomb007: talvez? Não tenho certeza se nasmdesambigua entre loopcomo um rótulo e loopa instrução de montagem, então apenas escrevo lopcomo todo mundo faz.
Matteo Italia

28

J, 32 28 bytes

Essa foi engraçada.

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

Explicação

É assim que esta solução funciona, incluindo uma explicação de como foi jogada no golfe.

   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
Muito agradável! A solução está cheia de ótimas peças!
Random #

1
(Eu costumo acrescentar um exemplo de invocação da função de usuários para não-experientes poderia experimentá-lo também.)
randomra

Esta solução faz minha cabeça doer:')
Nic Hartley

@QPaysTaxes Considero isso um elogio.
FUZxxl

@FUZxxl It is. Também é um trocadilho baseado em uma sequência de caracteres que aparece na sua resposta.
Nic Hartley

15

C, 150 bytes

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);}

Este foi louco divertido de golfe. Ainda não estou convencido de que acabei com isso.

Definimos uma única função f,, que leva a string como entrada e sai para stdout.

Vamos analisar o código, linha por linha:

/* 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!
}

Vou responder a qualquer pergunta que você possa ter!

Experimente um programa de teste online !


Quero lembrar que "char l = strlen (c) +1, o [l * l]" não é válido porque você não pode definir uma matriz de tamanho variável assim, mas faz 15 anos desde que tentei esse tipo em C.
Sparr

@Sparr Meu compilador nem lança um aviso. Acredito que esse era o padrão "oficialmente" em C99. Vou tentar encontrar uma referência para isso.
precisa saber é o seguinte

1
@Sparr Aqui está uma referência.
precisa saber é o seguinte

Obrigado. Parece coisas mudaram em torno de 15 (dar ou tomar um par) anos a este respeito :)
Sparr

1
@CoolGuy Isso, mas em chamadas subseqüentes de f, mnão seria redefinido para 0. Isso conta como "quebrar seu ambiente", proibido aqui .
BrainSteel 02/07

15

Retina + Bash, 27 bytes (14 + 10 + 3 = 27)

Isso faz uso de ANSI Escapes:

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

Equivalente a sed -e "s/(/(\\\e[B/g;s/)/\\\e[A)/g". O \e[Bcódigo de escape significa mover o cursor para baixo uma linha e o \e[Ameio mover o cursor para cima uma linha, portanto, esta solução simplesmente insere esses códigos antes e antes do início e do fim de cada par de parênteses aninhados. A entrada é passada pelo STDIN.

Você terá que chamá-lo printf $(Retina ...)para ver a saída corretamente.

Resultado

(((())))
(\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
Bem, nada mal! Se você pudesse apontar para um terminal específico que não precisa, printfseria ótimo. Caso contrário, acho que seria justo adicionar | printfà contagem de bytes.
Martin Ender

@ MartinBüttner Deve ser printf $()ou printf $(Retina ).
precisa saber é o seguinte

1
O que é isso Retina?
FUZxxl

2
@FUZxxl É a minha própria linguagem de programação baseada em regex. Veja GitHub .
Martin Ender

2
Por que \emais printf? Você pode simplesmente colocar os caracteres de controle no padrão de substituição.
Dennis

15

TI-BASIC, 69 60 56 55 bytes

Isto é para a família de calculadoras TI-83 + / 84 +, embora tenha sido escrita em uma edição 84+ C Silver Edition.

O programa aparece como maior no cálculo devido à inclusão de informações de tamanho + IVA. Além disso, existem mais de 56 caracteres aqui; o motivo é 56 bytes, porque todos os comandos com mais de um caractere são compactados em tokens com tamanho de um ou dois bytes.

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

Raspou outro byte graças a thomas-kwa ! (também dele foi o salto de 60 para 56.)


4
Ahhh, minha primeira linguagem de programação. Obrigado pela nostalgia, haha.
Alex Pritchard

1
Ainda programando a TI para a aula de matemática do ensino médio, muito útil para criar fórmulas que serão calculadas para você em testes e tarefas.
Elias Benevedes

1
Se você mudar as coisas, poderá usar o cos(piAnstruque para salvar outro byte.
lirtosiast

9

Python 2, 115 bytes

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)

Ligue como f("((()())()(()(())()))"), e a saída será STDOUT.

Explicação

Começamos com n = 0. Para cada caractere na linha de entrada:

  • Se o caracter for (, acrescentamos nespaços e aumentamosn
  • Se o caracter for ), diminuímos ne acrescentamos nespaços

O resultado é compactado e impresso. Observe que o zipzip do Python corresponde ao comprimento do elemento mais curto , por exemplo

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

Normalmente, usaria-se itertools.zip_longest( izip_longest) se quisessem zippreencher o comprimento do elemento mais longo .

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

Mas no Python 2, esse comportamento pode ser simulado pelo mapeamento None:

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

Python 3, 115 bytes

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)

Sem fechar, apenas preenchendo adequadamente ljust. Este parece ter algum potencial de golfe.


8

R, 151 127 caracteres

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)}

Com recuos e novas linhas:

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)
    }

Uso:

> 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
(                  )
 (    )()(        ) 
  ()()    ()(  )()  
             ()     

Ele lê a string como stdin, a divide como um vetor de caracteres únicos, calcula a soma acumulada de (e )subtrai a primeira com a segunda (com um atraso), calculando assim o "nível" de cada parêntese. Em seguida, imprime em stdout, para cada nível, os parênteses correspondentes ou um espaço.

Agradeço ao @MickyT por me ajudar a reduzi-lo consideravelmente!


2
+1 Solução agradável e elegante. Você pode salvar 6 substituindo for(i in n)cat(ifelse(D[i]-j," ",S[i]));cat("\n")por X=S;X[which(D!=j)]=' ';cat(X,sep='',fill=T). Então nnão é realmente necessário, mas você precisará alterar um pouco a parte do cumsum. D=c(C(S=="("),0)-c(0,C(S==")"));trazê-lo para baixo para 135.
MickyT

@MickyT wow thanks! não pensei nisso. whichaqui não é realmente necessário ( D!=jjá sendo um vetor de booleanos que permite a indexação). Eu não sabia o argumento fillde catque é um truque bacana! Obrigado por me fazer abreviá-lo com 24 caracteres surpreendentes !!
plannapus

8

C, 58 53 52 51 49 bytes

Utiliza seqüências de escape ANSI para mover a posição do cursor.

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

Se não estiver usando o gcc ou outro compilador compatível \e, ele poderá ser substituído \x1Bpor um total de 2 bytes extras. \e[Amove o cursor para cima uma linha e \e[Bmove o cursor para baixo uma linha. Não é necessário usar \e[Bpara mover uma linha para baixo, pois são dois bytes mais curtos para usar o caractere de tabulação vertical ASCII 0xBou \v.

A sequência de entrada é assumida, a partir da pergunta, como composta apenas entre parênteses (balanceados), portanto, verificar a paridade do caractere com &1é suficiente para distinguir entre (e ).


7

Pip, 53 bytes

Pip é uma linguagem de código-golfe da minha invenção. A primeira versão foi publicada no sábado, para que eu possa oficialmente dar uma volta! A solução abaixo não é tão competitiva quanto os idiomas de golfe, mas isso se deve em parte ao fato de ainda não ter implementado coisas como zip e max.

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

Espera a sequência de parênteses como um argumento da linha de comandos.

Versão "Ungolfed":

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

Explicação:

Ao contrário da maioria das linguagens de golfe, o Pip é imprescindível para os operadores de infix, portanto a sintaxe é um pouco mais próxima do C e de seus derivados. Também empresta idéias da programação funcional e baseada em array. Veja o repositório para mais documentação.

O programa primeiro gera uma lista de profundidades (armazenando-a z) mapeando uma função para a sequência de entrada a. A variável global vrastreia o nível atual. (Variáveis a-gno Pip são variáveis ​​de função local, mas h-zsão globais. vÉ útil porque é pré-inicializado para -1.)

Em seguida, usamos um Wloop hile para gerar e imprimir cada linha, até a linha gerada consistir em todos os espaços. vagora é usado para colunas e ilinhas. A {z@++v=i?as}função, mapeada repetidamente para a sequência de entrada original, testa se a linha atual icorresponde à linha em que o parêntese atual deve estar (como armazenado na zlista). Nesse caso, use o parêntese ( a); caso contrário, use s(pré-inicializado para o espaço). O resultado final é que, em cada iteração, oé atribuída uma lista de caracteres equivalente à próxima linha da saída.

Para testar se devemos continuar fazendo loop, verificamos se otodos os espaços RM'd estão vazios. Caso contrário, imprima-o (que por padrão concatena tudo junto como no CJam), redefina o número da coluna para -1 e aumente o número da linha.

(Curiosidade: inicialmente, eu tinha uma solução de 51 bytes ... que não funcionou porque ocorreu um erro no intérprete.)


7

Pitão, 31 bytes

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

Experimente online.

-/<zk\(/<zhk\): Encontra o nível apropriado para a posição atual do caractere.

?YqN-/<zk\(/<zhk\)d: Um espaço se o nível apropriado não for o nível atual, caractere atual caso contrário.

Js.e?YqN-/<zk\(/<zhk\)dz: Gere a string, salve-a em J.

I-JdJ: Se Jnão houver todos os espaços, imprima-os.

Vz: zTempos de loop .


6

GNU Bash + coreutils + travessão, 135

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

Entrada / saída via STDIN / STDOUT:

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

indentfaz a maior parte do trabalho pesado, mas precisa trabalhar com aparelho em vez de parênteses. O resto é modificação desta resposta para transpor a saída de indent.


5

Python 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)

Imprime linha por linha. Para um determinado número de linha i(na verdade, sua negação), passa pela sequência de entrada se cria uma nova sequência zque contém apenas os caracteres de sprofundidade i. Isso é feito incrementando ou decrementando ipara rastrear a profundidade atual e adicionando os caracteres atuais quando ié 0ajustado para o tipo de parênteses e adicionando um espaço.

Em seguida, imprime e retorna para a próxima i, a menos que a linha atual tenha todos os espaços. Observe que, como as parênteses são equilibradas, o iloop posterior é o mesmo que no início.

Python 3 seria o mesmo, exceto por um caractere print(z).


5

trapaça :( Retina + TeX, N bytes trapaça :(

Isso só funciona se você renderizar (?) A saída usando MathJax ou algum outro TeX, que está atualmente desativado para este SE :(

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

Cada linha deve estar em um arquivo diferente, mas você pode testá-lo usando Retina -e "\(" -e "({" -e "\)" -e "})" -e "\{\(" -e "_{("(ou o comando sed equivalente sed -e "s/(/({/g;s/)/})/g;s/{(/_{(/g"). A entrada é passada pelo STDIN.

Isso funciona colocando o conteúdo de cada par de parênteses entre chaves e depois inscrevendo todos os itens dentro deles.

Resultado

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

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

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

Saída TeX


1
Fico lisonjeado por você ter usado o Retina, e isso é bom pensar fora da caixa, mas não é exatamente assim que a saída deve ser. ;) Em particular, isso viola a formulação alternativa "Outra maneira de ver é que os parênteses na profundidade n são movidos para a linha n, mantendo sua posição horizontal". Eu ficaria muito impressionado com uma solução Retina pura e em conformidade com as regras, e poderia oferecer uma recompensa por isso. ;)
Martin Ender

In total the lines must not be longer than twice the length of the input string. Alterando a linha 2 para (\,{e da linha 4 para }\,)significa que a saída se encaixa nesta (embora a profundidade vertical ainda está errado: ()
user22723

Bem, eu consegui fazer solução regra compatível com:)
user22723

1
Bom trabalho. Acho que isso significa que você pode excluir a resposta mais barata agora. ;)
Martin Enders

5

Java, 232 226 224 222 bytes

Versão Golfed:

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':' ');}

Versão longa:

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':' '));
}

A string de entrada é analisada primeiro, procurando "(" e ")" para adicionar / subtrair um contador e armazenar seu valor, determinando a que distância os parênteses devem ir em uma matriz, além de acompanhar o quão profundo é o mais profundo. Então a matriz é analisada; os parênteses com valores menores são impressos primeiro e continuarão imprimindo linha por linha até atingir o máximo.

Provavelmente vou encontrar maneiras de jogar isso ainda mais tarde.


5

Javascript / ES6, 97 caracteres

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)}}

Uso

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

Explicação

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

Em vez de n<m?console.log(o):0, você pode usar o n<m&&console.log(o)que salva 1 byte.
Ismael Miguel

4

CJam, 43 41 36 bytes

Não sou muito jogador de golfe (acho), mas aqui vai minha primeira tentativa:

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

Como funciona

Eu estou usando o fato muito útil de que )e (no CJam significam incremento e decremento, respectivamente. Assim, eu simplesmente avalio os colchetes para obter a profundidade.

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";

Experimente online aqui


4

Oitava, 85 caracteres

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

É uma otimização da abordagem ingênua, o que é realmente bastante natural para o Matlab e o 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;

A tabela t talvez ainda não exista, e podemos atribuir a qualquer elemento imediatamente, e é remodelada para a menor dimensão necessária para a existência desse elemento, o que é bastante conveniente.


4

Perl, 91 89 88 84 80 79 bytes

$t=<>;{$_=$t;s/\((?{$l++})|.(?{--$l})/$^R==$c?$&:$"/ge;print,++$c,redo if/\S/}
  • $ t é a sequência de entrada.
  • $ c é a profundidade que queremos imprimir na linha atual.
  • $ l é a profundidade em que estamos depois de encontrar um parêntese.
  • $ l é atualizado nos blocos de código incorporado regex .
  • $ ^ R é o resultado do bloco de código mais recente.

4

Haskell, 154 bytes

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]]

mesma idéia que a outra solução Haskell, mas um pouco menor. - Uso:

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

3

J, 46

Não é tão bom quanto as outras "línguas do golfe", mas em minha defesa: J é péssimo com as cordas.

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

Toma a string como entrada para uma função. Provavelmente também há uma maneira melhor de fazê-lo em J.

Uso:

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

Veja minha resposta para outra maneira de fazer isso em J.
FUZxxl

3
Pessoalmente, acho que J é perfeitamente adequado para strings. Você só precisa pensar com matrizes.
FUZxxl

3

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

Explicação:

->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 bytes

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]);}

Recuado:

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]);
}

Acho que o ciclo final pode ser encurtado, mas deixarei como um exercício para o leitor. ;-)


Antigo, 233 bytes de resposta:

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));}

Recuado:

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));
}

Sei que já faz mais de um ano, mas "acho que o ciclo final pode ser encurtado, mas deixarei isso como um exercício para o leitor. ;-)"; você está realmente certo. Pode ser alterado de for(x=0;x<l*l;x++)System.out.print((x%l==0?"\n":"")+m[x]);para for(x=0;x<l*l;)System.out.print((x%l==0?"\n":"")+m[x++]);para -1 byte. Além disso, você pode salvar mais 2 bytes removendo p=x=0e apenas usando int p=0,x=0,na inicialização dos campos. No total, torna-se 211 bytes .
Kevin Cruijssen

3

C #, 195 bytes

Primeiro tente jogar golfe - grite se fiz algo errado.

Versão alternativa do C # usando SetCursorPosition e trabalhando da esquerda para a direita, recebendo a entrada como um argumento de linha de comando.

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++;}}}

Eu pensei que seria divertido ajustar a posição de gravação com base no paren abrir / fechar e não nas linhas completas. Fechar paren move a posição para cima antes de escrever; paren aberto move-o para baixo após a gravação. A ação SetCursorPosition salva cinco bytes. Mover o cursor para a próxima linha após a saída levaria um pouco mais.

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

Lote, 356 335 bytes

Eu sei que já existe uma solução em lote para esse desafio, mas essa é significativamente maior e parece ter uma abordagem diferente. Mais importante ainda, a outra solução em lote contém pelo menos um comando powershell; Esta solução não.

@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.)

Há um caractere de backspace ( U+0008) na penúltima linha após o ponto (linha 12, coluna 57). Isso não é visível no código postado aqui, mas está incluído na contagem de bytes.


Alguém realmente enviando uma resposta no Lote - Agradável +1.
unclemeat

3

Lote, 424 bytes

@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!

Sem golfe:

@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!

Exemplo:

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

3

C, 118 117 bytes

Outra resposta em C, mas a minha é mais curta.

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("");}}

Versão não destruída:

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("");
    }
}

E funciona!

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

1
Uma solução bastante elegante, no entanto, putchar(c-d?32:*p)é um caractere menor que putchar(c==d?*p:32).
pawel.boczarski

2

Haskell, 227 bytes

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
Você pode economizar alguns espaços com operadores: por exemplo, em n#[]vez de m n [].
Franky

2

Perl, 76 bytes

$a[/\(/?$l++:--$l][$i++]=$_ for split//,<>;print map{$_||' '}@$_,"\n"for@a

Não use strictaqui :)


2

Lex, 94 bytes

Depende dos códigos do console Linux. Com o gcc, você pode cortar quatro bytes substituindo as duas instâncias \33por um caractere de escape real.

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

Para compilar e executar:

$ flex -o telescopic.c telescopic.l
$ gcc -o telecopic telescopic.c -lfl
$ ./telescopic
(()(()())()((())))(())
(                )(  )
 ()(    )()(    )  ()
    ()()    (  )
             ()
--- type ctrl-D ---
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.