Parentesi telescopiche


79

Considera una stringa non vuota di parentesi correttamente bilanciate:

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

Possiamo immaginare che ogni coppia di parentesi rappresenti un anello in una costruzione telescopica crollata . Quindi estendiamo il telescopio:

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

Un altro modo di vederlo è che le parentesi alla profondità n vengono spostate sulla linea n , mantenendo la loro posizione orizzontale.

Il tuo compito è prendere una tale stringa di parentesi bilanciate e produrre la versione estesa.

È possibile scrivere un programma o una funzione, prendendo input tramite STDIN (o l'equivalente più vicino), argomento della riga di comando o parametro di funzione e producendo output tramite STDOUT (o equivalente più vicino), valore di ritorno o parametro di funzione (out).

Si può presumere che la stringa di input sia valida, ovvero sia composta solo da parentesi, che sono correttamente bilanciate.

È possibile stampare spazi finali su ciascuna riga, ma non più spazi iniziali del necessario. In totale le linee non devono essere più lunghe del doppio della lunghezza della stringa di input. Se lo si desidera, è possibile stampare una nuova riga finale.

Esempi

Oltre all'esempio sopra, qui ci sono alcuni altri casi di test (input e output sono separati da una riga vuota).

()

()
(((())))

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

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

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

Sfide correlate:

  • Stringhe topografiche , che ti chiedono di produrre ciò che è essenzialmente il complemento del risultato in questa sfida.
  • Code Explanation Formatter , un'ampia generalizzazione delle idee in questa sfida, pubblicata di recente da PhiNotPi. (In effetti, la descrizione originale di PhiNotPi della sua idea era ciò che ha ispirato questa sfida.)

Classifiche

Eh, questo ha ottenuto molta partecipazione, quindi ecco uno snippet di stack per generare sia una classifica regolare che una panoramica dei vincitori per lingua.

Per assicurarti che la tua risposta venga visualizzata, ti preghiamo di iniziare la risposta con un titolo, utilizzando il seguente modello Markdown:

# Language Name, N bytes

dov'è Nla dimensione del tuo invio. Se si migliora il punteggio, è possibile mantenere i vecchi punteggi nel titolo, colpendoli. Per esempio:

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


17
Titolo alternativo: De-Lisp-ify una stringa. : P
Alex A.

1
Ci sono restrizioni sul colore dell'output?
Matteo Italia,

1
@ MartinBüttner: non importa, ho trovato un modo più pulito; diciamo solo che la mia idea precedente avrebbe rasato un byte lasciando tutte le parentesi chiuse che lampeggiavano blu su ciano ... :-)
Matteo Italia

8
@MatteoItalia oh dio, sono contento che non sia successo. ;)
Martin Ender,

12
@MatteoItalia: pubblica quella versione! Vale la pena vederlo.
user2357112

Risposte:


8

CJam, 17 16 15 byte

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

Quanto sopra è un dump xxd reversibile, poiché il codice sorgente contiene i caratteri non stampabili VT (0x0b) e CSI (0x9b).

Come questa risposta , utilizza sequenze di escape ANSI , ma utilizza anche schede verticali e stampa direttamente i caratteri di controllo per evitare l'uso di printf .

Ciò richiede un terminale di testo video di supporto, che include la maggior parte degli emulatori di terminale non Windows.

Prova

Dobbiamo impostare la variabile di shell LANG e la codifica dell'emulatore di terminale su ISO 8859-1. Il primo si ottiene eseguendo

$ LANGsave="$LANG"
$ LANG=en_US

Inoltre, prima di eseguire il codice effettivo, disabiliteremo il prompt e cancelleremo lo schermo.

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

Questo assicura che l'output sia mostrato correttamente.

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

Per ripristinare LANG e il prompt, eseguire questo:

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

Come funziona

Inseriamo una scheda verticale dopo ciascuna ( per spostare il cursore verso il basso e la sequenza di byte 9b 41 ( "\x9bA") prima di ciascuna ) per spostare il cursore verso l'alto.

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

codice macchina x86, 39 34 33 30 29 byte

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

assembly x86 per DOS, con alcuni trucchi:

    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

Limitazioni :

  • stampa sempre a partire dalla parte inferiore dello schermo, senza prima cancellare; un clsprima di correre è quasi obbligatorio;
  • i colori sono brutti; questa è la conseguenza del riciclo del carattere successivo come attributo di colore per salvare due byte qua e là;
  • il codice assume bh=0e l'indicatore di direzione si cancella all'avvio, entrambi non documentati; OTOH, bxè esplicitamente impostato su zero in tutte le varianti di DOS che ho visto (DosBox, MS-DOS 2, FreeDOS) e ovunque ho testato le bandiere erano già OK.

inserisci qui la descrizione dell'immagine


Ho appena verificato questo. Sì funziona. Sei sicuro di dover fare cld?
FUZxxl

@FUZxxl: su DosBox funziona bene anche senza di esso, ma guardando le sue fonti dice che i flag sono preservati da qualsiasi cosa sia accaduta in DOS e in TRS prima, quindi probabilmente sarebbe necessario giocarlo in sicurezza. Comunque, sarebbe solo un byte, il vero vantaggio sarebbe quello di uccidere almeno uno di quei grandi (= 4 byte ciascuno) add/ sub.
Matteo Italia,

Hm ... nessuna idea, davvero.
FUZxxl,

Puoi cambiare lopin loop?
mbomb007,

@ mbomb007: forse? Non sono sicuro che sia nasmchiaro loopcome un'etichetta e loople istruzioni di assemblaggio, quindi scrivo lopcome fanno tutti gli altri.
Matteo Italia,

28

J, 32 28 byte

Questo è stato divertente.

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

Spiegazione

Ecco come funziona questa soluzione, inclusa una spiegazione di come è stata giocata a golf.

   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
Molto bella! La soluzione è piena di parti fantastiche!
randomra,

1
(Di solito aggiungo un esempio di invocazione della funzione in modo che anche gli utenti non esperti possano provarla.)
randomra

Questa soluzione mi fa male alla testa:')
Nic Hartley,

@QPaysTaxes Lo prendo come un complimento.
FUZxxl,

@FUZxxl Lo è. È anche un gioco di parole basato su una sequenza di caratteri che appare nella tua risposta.
Nic Hartley,

15

C, 150 byte

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

Questo è stato un divertimento folle nel golf. Non sono ancora convinto di averlo finito.

Definiamo una singola funzione, fche prende la stringa come input e output su stdout.

Esaminiamo il codice, riga per riga:

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

Risponderò a qualsiasi domanda tu possa avere!

Prova un programma di test online !


Voglio ricordare che "char l = strlen (c) +1, o [l * l]" non è valido perché non puoi definire un array di dimensioni variabili come quello, ma sono passati 15 anni da quando ho provato che tipo in C.
Sparr

@Sparr Il mio compilatore non lancia nemmeno un avviso. Credo che questo fosse "ufficialmente" standard in C99. Proverò a trovare un riferimento per questo.
BrainSteel,

1
@Sparr Ecco un riferimento.
BrainSteel,

Grazie. Sembra che le cose siano cambiate intorno ai 15 (dare o prendere un paio) anni fa a questo proposito :)
Sparr

1
@CoolGuy Lo farebbe, ma nelle successive chiamate di f, mnon si reimposterà su 0. Ciò conta come "violazione del tuo ambiente", vietato qui .
BrainSteel,

15

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

Questo utilizza ANSI Escapes:

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

Equivalente a sed -e "s/(/(\\\e[B/g;s/)/\\\e[A)/g". Il \e[Bcodice di escape significa spostare il cursore in basso di una riga e il \e[Amezzo sposta il cursore in alto di una riga, quindi questa soluzione inserisce semplicemente quei codici dopo e prima dell'inizio e della fine di ciascuna coppia nidificata di parentesi. L'ingresso viene passato tramite STDIN.

Dovrai chiamarlo printf $(Retina ...)per vedere correttamente l'output.

Produzione

(((())))
(\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
Bene, non male! Se potessi indicare un terminale specifico che non è necessario, printfsarebbe fantastico. Altrimenti, penso che sarebbe giusto aggiungere | printfal conteggio dei byte.
Martin Ender,

@ MartinBüttner Dovrebbe essere printf $()o printf $(Retina ).
jimmy23013,

1
Cos'è quella cosa di Retina?
FUZxxl,

2
@FUZxxl È il mio linguaggio di programmazione basato su regex. Vedi GitHub .
Martin Ender,

2
Perché \epiù printf? È possibile semplicemente inserire i caratteri di controllo nel modello di sostituzione.
Dennis,

15

TI-BASIC, 69 60 56 55 byte

Questo è per la famiglia di calcolatori TI-83 + / 84 +, sebbene sia stato scritto su una Silver Edition 84+ C.

Il programma si presenta come on-calc più grande a causa dell'IVA + informazioni sulla dimensione incluse. Inoltre, ci sono più di 56 caratteri qui; il motivo è di 56 byte perché tutti i comandi che contengono più di un carattere sono compressi in token di dimensioni di uno o due byte.

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

Rasato un altro byte grazie a Thomas-Kwa ! (anche da lui è stato il salto dal 60 al 56.)


4
Ahhh, il mio primo linguaggio di programmazione. Grazie per la nostalgia, ahah.
Alex Pritchard,

1
Sto ancora programmando TI per la classe di matematica delle scuole superiori, molto utile avere formule incorporate che calcoleranno per te su test e incarichi.
Elias Benevedes,

1
Se sposti le cose puoi usare il cos(piAnstrucco per salvare un altro byte.
lirtosiast

9

Python 2, 115 byte

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)

Chiama like f("((()())()(()(())()))")e l'output è su STDOUT.

Spiegazione

Iniziamo con n = 0. Per ogni carattere nella riga di input:

  • Se il carattere è (, anteponiamo gli nspazi, quindi incrementiamon
  • Se il carattere lo è ), diminuiamo, nquindi anteponiamo gli nspazi

Il risultato viene quindi zippato e stampato. Nota che le zipzip di Python corrispondono alla lunghezza dell'elemento più corto , ad es

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

Di solito si userebbe itertools.zip_longest( izip_longest) se si volesse zipriempire per la lunghezza dell'elemento più lungo .

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

Ma in Python 2, questo comportamento può essere simulato mappando None:

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

Python 3, 115 byte

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)

Nessuna cerniera, solo imbottitura in modo appropriato con ljust. Questo sembra avere un potenziale di golf.


8

R, 151 127 caratteri

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

Con rientri e righe:

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

Legge la stringa come stdin, la divide come vettore di singoli caratteri, calcola la somma cumulativa di (e ), sottrae la prima con la seconda (con un ritardo) calcolando così il "livello" di ciascuna parentesi. Quindi stampa su stdout, per ogni livello, le parentesi corrispondenti o uno spazio.

Grazie a @MickyT per avermi aiutato ad accorciarlo considerevolmente!


2
+1 Soluzione piacevole ed elegante. Puoi salvare 6 sostituendolo for(i in n)cat(ifelse(D[i]-j," ",S[i]));cat("\n")con X=S;X[which(D!=j)]=' ';cat(X,sep='',fill=T). Quindi nnon è davvero necessario, ma dovresti cambiare un po 'la parte del cumsum. D=c(C(S=="("),0)-c(0,C(S==")"));portandolo a 135.
MickyT

@MickyT wow grazie! non ci ho pensato. whichnon è davvero necessario qui ( D!=jessendo già un vettore di booleani che consente l'indicizzazione). Non sapevo argomento fillper cat, questo è un trucco nifty! Grazie per avermi fatto accorciare di un sorprendente 24 caratteri !!
plannapus,

8

C, 58 53 52 51 49 byte

Utilizza le sequenze di escape ANSI per spostare la posizione del cursore.

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

Se non si utilizza gcc o un altro compilatore che supporti \e, può essere sostituito con \x1Bun totale di 2 byte extra. \e[Asposta il cursore in alto di una riga e \e[Bsposta il cursore in basso di una riga. Non è necessario utilizzare \e[Bper spostarsi verso il basso di una riga poiché è più breve di due byte per utilizzare il carattere di scheda verticale ASCII 0xBo \v.

Si presume che la stringa di input sia composta solo da parentesi (bilanciate), quindi &1è sufficiente controllare la parità del carattere con , per distinguere tra (e ).


7

Pip, 53 byte

Pip è un linguaggio da golf di codice della mia invenzione. La prima versione è stata pubblicata sabato, quindi posso ufficialmente provarla! La soluzione che segue non è terribilmente competitiva con le lingue del golf, ma è in parte perché non ho ancora implementato cose come zip e max.

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

Si aspetta che la stringa di parentesi sia un argomento della riga di comando.

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

Spiegazione:

A differenza della maggior parte dei linguaggi del golf, Pip è un imperativo con gli operatori infix, quindi la sintassi è leggermente più vicina a C e ai suoi derivati. Prende in prestito idee dalla programmazione funzionale e basata su array. Vedere il repository per ulteriore documentazione.

Il programma genera prima un elenco di profondità (memorizzandolo in z) mappando una funzione sulla stringa di input a. La variabile globale vtiene traccia del livello corrente. (Le variabili a-gin Pip sono variabili locali della funzione, ma h-zsono globali. vÈ utile perché è preinizializzato a -1.)

Successivamente, utilizziamo un Wciclo hile per generare e stampare ogni riga, fino a quando la riga generata sarà composta da tutti gli spazi. vè ora utilizzato per le colonne e iper le righe. La {z@++v=i?as}funzione, ripetutamente mappata sulla stringa di input originale, verifica se la riga corrente icorrisponde alla riga su cui dovrebbe essere attiva la parentesi corrente (come memorizzata znell'elenco). In tal caso, utilizzare la parentesi ( a); in caso contrario, utilizzare s(preinizializzato nello spazio). Il risultato finale è che ad ogni iterazione, oviene assegnato un elenco di caratteri equivalente alla riga successiva dell'output.

Per verificare se dovremmo continuare il loop, controlliamo se ocon tutti gli spazi RM'd è vuoto. In caso contrario, stampalo (che per impostazione predefinita concatena tutto insieme come in CJam), reimposta il numero di colonna su -1 e incrementa il numero di riga.

(Curiosità: all'inizio avevo una soluzione a 51 byte ... che non funzionava perché ha rivelato un bug nell'interprete.)


7

Pyth, 31 byte

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

Provalo online.

-/<zk\(/<zhk\): Trova il livello appropriato per la posizione attuale del personaggio.

?YqN-/<zk\(/<zhk\)d: Uno spazio se il livello appropriato non è il livello corrente, altrimenti il ​​carattere corrente.

Js.e?YqN-/<zk\(/<zhk\)dz: Genera la stringa, salvala in J.

I-JdJ: Se Jnon tutti gli spazi, stampalo.

Vz: zTempi di ciclo .


6

GNU Bash + coreutils + indent, 135

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

Ingresso / uscita tramite STDIN / STDOUT:

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

indentfa la maggior parte del sollevamento pesante, ma deve lavorare con le parentesi graffe anziché con le parentesi. Il resto è la modifica di questa risposta per trasporre l'output di 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)

Stampa riga per riga. Per un dato numero di riga i(in realtà, la sua negazione), passa attraverso la stringa di input se crea una nuova stringa zche contiene solo i caratteri di sapprofondimento i. Questo viene fatto incrementando o decrementando iper tenere traccia della profondità corrente e aggiungendo i caratteri correnti quando iviene 0regolato per il tipo di paren, e altrimenti aggiungendo uno spazio.

Quindi, stampa e ricorre al successivo a imeno che la riga corrente fosse tutti gli spazi. Si noti che poiché le parentesi sono bilanciate, il iciclo successivo è uguale all'inizio.

Python 3 sarebbe lo stesso tranne che per un personaggio di print(z).


5

barare :( Retina + TeX, N byte barare :(

Funziona solo se si esegue il rendering (?) Dell'output usando MathJax o qualche altro TeX, che è attualmente disabilitato per questo SE :(

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

Ogni riga dovrebbe essere in un file diverso, ma puoi provarlo usando Retina -e "\(" -e "({" -e "\)" -e "})" -e "\{\(" -e "_{("(o il comando sed equivalente sed -e "s/(/({/g;s/)/})/g;s/{(/_{(/g"). L'ingresso viene passato tramite STDIN.

Funziona racchiudendo tra parentesi il contenuto di ciascuna coppia di parentesi e quindi sottoscrivendo tutti gli elementi al loro interno.

Produzione

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

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

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

Uscita TeX


1
Sono lusingato che tu abbia usato Retina, e questo è bello pensare fuori dagli schemi, ma non è proprio quello che dovrebbe essere l'output. ;) In particolare, ciò viola la formulazione alternativa "Un altro modo di vederlo è che le parentesi alla profondità n vengono spostate sulla linea n, mantenendo la loro posizione orizzontale". Sarei molto colpito da una soluzione Retina pura, conforme alle regole, e potrei distribuirgli una taglia. ;)
Martin Ender,

In total the lines must not be longer than twice the length of the input string. Cambiare la linea 2 (\,{e la linea 4 }\,)significa che l'uscita si adatta a questo (sebbene la profondità verticale sia ancora errata: ()
user22723

Bene, sono riuscito a creare una soluzione conforme alle regole
:)

1
Bel lavoro. Immagino che ciò significhi che ora puoi eliminare la risposta economica. ;)
Martin Ender il

5

Java, 232 226 224 222 byte

Versione golfizzata:

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

Versione lunga:

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

La stringa di input viene analizzata per prima, cercando "(" e ")" per aggiungere / sottrarre un contatore e memorizzarne il valore determinando fino a che punto le parentesi dovrebbero andare in un array, tenendo anche traccia della profondità della profondità. Quindi l'array viene analizzato; le parentesi con valori inferiori vengono stampate per prime e continueranno a stampare riga per riga fino a raggiungere il massimo.

Probabilmente troverò il modo di giocare a golf più avanti.


5

Javascript / ES6, 97 caratteri

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

Spiegazione

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

Invece di n<m?console.log(o):0, è possibile utilizzare n<m&&console.log(o)quale salva 1 byte.
Ismael Miguel,

4

CJam, 43 41 36 byte

Non troppo golf (credo), ma ecco il mio primo tentativo:

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

Come funziona

Sto usando il fatto molto utile che )e (in CJam significano rispettivamente incremento e decremento. Pertanto, valuto semplicemente le parentesi per ottenere la profondità.

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

Provalo online qui


4

Ottava, 85 caratteri

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

È un'ottimizzazione dell'approccio ingenuo, che in realtà è abbastanza naturale per Matlab e 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;

La tabella t potrebbe anche non esistere ancora, e potremmo assegnare immediatamente a qualsiasi elemento, e rimodella alla dimensione più piccola necessaria per l'esistenza di questo elemento che è abbastanza conveniente.


4

Perl, 91 89 88 84 80 79 byte

$t=<>;{$_=$t;s/\((?{$l++})|.(?{--$l})/$^R==$c?$&:$"/ge;print,++$c,redo if/\S/}
  • $ t è la stringa di input.
  • $ c è la profondità che vogliamo stampare sulla riga corrente.
  • $ l è la profondità che ci troviamo dopo aver incontrato una parentesi.
  • $ l viene aggiornato in blocchi di codice integrati regex .
  • $ ^ R è il risultato del blocco di codice più recente.

4

Haskell, 154 byte

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

stessa idea dell'altra soluzione Haskell, ma un po 'più breve. - Utilizzo:

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

3

J, 46

Non eccezionale come le altre "lingue del golf", ma a mia difesa: J è terribile con le corde.

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

Prende la stringa come input per una funzione. Probabilmente c'è anche un modo migliore per farlo in J.

Uso:

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

Vedi la mia risposta per un altro modo di farlo in J.
FUZxxl

3
Personalmente, penso che J sia perfettamente adatto per le stringhe. Devi solo pensare con le matrici.
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]}}

Spiegazione:

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

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

rientrato:

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

Immagino che il ciclo finale potrebbe essere abbreviato, ma lo lascerò come esercizio al lettore. ;-)


Vecchia risposta da 233 byte:

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

rientrato:

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

So che è passato più di un anno, ma "Immagino che il ciclo finale potrebbe essere abbreviato, ma lo lascerò come esercizio al lettore. ;-)"; hai davvero ragione. Può essere modificato da for(x=0;x<l*l;x++)System.out.print((x%l==0?"\n":"")+m[x]);a for(x=0;x<l*l;)System.out.print((x%l==0?"\n":"")+m[x++]);per -1 byte. Inoltre, puoi salvare altri 2 byte rimuovendoli p=x=0e utilizzandoli int p=0,x=0,al momento dell'inizializzazione dei campi. In totale diventa 211 byte .
Kevin Cruijssen,

3

C #, 195 byte

Prima prova a golf - urla se ho fatto qualcosa di sbagliato.

Versione alternativa C # usando SetCursorPosition e lavorando da sinistra a destra prendendo l'input come arg da riga di 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++;}}}

Ho pensato che sarebbe stato divertente regolare la posizione di scrittura in base alla parentesi aperta / chiusa e non alle linee complete. Close paren sposta la posizione in alto prima di scrivere; open paren lo sposta in basso dopo aver scritto. L'azione SetCursorPosition salva cinque byte. Spostare il cursore sulla riga successiva dopo l'output richiederebbe un po 'di più.

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

Lotto, 356 335 byte

So che esiste già una soluzione Batch per questa sfida, ma questa è molto più giocata e sembra adottare un approccio diverso. Ancora più importante, l'altra soluzione batch contiene almeno un comando PowerShell; questa soluzione no.

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

C'è un carattere backspace ( U+0008) sulla penultima riga che segue il punto (riga 12, colonna 57). Questo non è visibile nel codice pubblicato qui, ma è incluso nel conteggio dei byte.


Qualcun altro ha effettivamente inviato una risposta in Batch - Nice one +1.
salato

3

Lotto, 424 byte

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

Un-giocato a golf:

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

Esempio:

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

3

C, 118 117 byte

Un'altra risposta in C, ma la mia è più breve.

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

Versione non golfata:

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

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

1
Piuttosto una soluzione elegante, tuttavia putchar(c-d?32:*p)è un personaggio più corto di putchar(c==d?*p:32).
pawel.boczarski,

2

Haskell, 227 byte

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
Puoi salvare alcuni spazi con gli operatori: ad es. n#[]Anziché m n [].
Franky,

2

Perl, 76 byte

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

No use strictqui :)


2

Lex, 94 byte

Dipende dai codici della console Linux. Con gcc, puoi tagliare quattro byte sostituendo entrambe le istanze \33con un carattere di escape reale.

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

Per compilare ed eseguire:

$ flex -o telescopic.c telescopic.l
$ gcc -o telecopic telescopic.c -lfl
$ ./telescopic
(()(()())()((())))(())
(                )(  )
 ()(    )()(    )  ()
    ()()    (  )
             ()
--- type ctrl-D ---
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.