Parenthèses télescopiques


79

Considérons une chaîne non vide de parenthèses correctement équilibrées:

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

On peut imaginer que chaque paire de parenthèses représente un anneau dans une construction télescopique effondrée . Alors étendons le télescope:

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

Une autre façon de voir les choses est que les parenthèses à la profondeur n sont déplacées vers la ligne n , tout en conservant leur position horizontale.

Votre tâche consiste à prendre une telle chaîne de parenthèses équilibrées et à produire la version étendue.

Vous pouvez écrire un programme ou une fonction en prenant une entrée via STDIN (ou son équivalent le plus proche), un argument de ligne de commande ou un paramètre de fonction et en produisant une sortie via un paramètre STDOUT (ou son équivalent le plus proche), une valeur de retour ou une fonction (out).

Vous pouvez supposer que la chaîne d'entrée est valide, c'est-à-dire qu'elle ne comprend que des parenthèses correctement balancées.

Vous pouvez imprimer des espaces en fin de ligne sur chaque ligne, mais pas plus que nécessaire. Au total, les lignes ne doivent pas dépasser deux fois la longueur de la chaîne d'entrée. Vous pouvez éventuellement imprimer une nouvelle ligne de fin.

Exemples

En plus de l'exemple ci-dessus, voici quelques tests supplémentaires (les entrées et les sorties sont séparées par une ligne vide).

()

()
(((())))

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

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

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

Défis associés:

  • Topographic Strings , qui vous demande de produire ce qui est essentiellement le complément de la sortie dans ce défi.
  • Code Explanation Formatter , une large généralisation des idées de ce défi, publié récemment par PhiNotPi. (En fait, la description originale de son idée par PhiNotPi était ce qui a inspiré ce défi.)

Classements

Euh, cela a eu beaucoup de participation, alors voici un extrait de pile pour générer à la fois un classement régulier et un aperçu des gagnants par langue.

Pour vous assurer que votre réponse apparaît, commencez votre réponse par un titre, en utilisant le modèle Markdown suivant:

# Language Name, N bytes

Nest la taille de votre soumission. Si vous améliorez votre score, vous pouvez conserver les anciens scores en les effaçant. Par exemple:

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


17
Titre alternatif: De-Lisp-ify une chaîne. : P
Alex A.

1
Existe-t-il des restrictions sur la couleur de la sortie?
Matteo Italia

1
@ MartinBüttner: tant pis, j'ai trouvé un moyen plus propre; Disons simplement que mon idée précédente aurait rasé un octet en laissant toutes les parenthèses fermées clignotant en bleu sur le cyan ... :-)
Matteo Italia

8
@ MatteoItalia oh mon dieu, je suis heureux que cela ne soit pas arrivé. ;)
Martin Ender

12
@MatteoItalia: Publiez cette version! Ça vaut la peine d'être vu.
user2357112

Réponses:


8

CJam, 17 16 15 octets

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

Ce qui précède est un vidage xxd réversible, car le code source contient les caractères non imprimables VT (0x0b) et CSI (0x9b).

Comme cette réponse , il utilise des séquences d'échappement ANSI , mais il utilise également des tabulations verticales et imprime directement les caractères de contrôle pour éviter l'utilisation de printf .

Cela nécessite un terminal vidéo texte compatible, qui inclut la plupart des émulateurs de terminal non Windows.

Essai

Nous devons définir la variable shell LANG et le codage de l'émulateur de terminal sur ISO 8859-1. Le premier est réalisé en exécutant

$ LANGsave="$LANG"
$ LANG=en_US

De plus, avant d'exécuter le code actuel, nous allons désactiver l'invite et effacer l'écran.

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

Cela garantit que la sortie est affichée correctement.

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

Pour restaurer LANG et l'invite, exécutez ceci:

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

Comment ça fonctionne

Nous insérons une tabulation verticale après chaque ( pour déplacer le curseur vers le bas et la séquence d'octets 9b 41 ( "\x9bA") avant chacun ) pour déplacer le curseur vers le haut.

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

code machine x86, 39 34 33 30 29 octets

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

Assemblage x86 pour DOS, avec quelques astuces:

    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

Limitations :

  • il imprime toujours à partir du bas de l’écran, sans effacer d’abord; un clsavant d' exécuter est presque obligatoire;
  • les couleurs sont laides; c’est la conséquence du recyclage du caractère suivant en tant qu’attributs de couleur pour économiser deux octets ici et là;
  • le code suppose bh=0et l'indicateur de direction est dégagé au début, tous deux non documentés; OTOH bxest explicitement mis à zéro dans toutes les variantes DOS que j'ai vues (DosBox, MS-DOS 2, FreeDOS), et partout où j'ai testé les indicateurs étaient déjà OK.

entrez la description de l'image ici


Je viens de vérifier cela. Oui cela fonctionne. Êtes-vous sûr de devoir faire cld?
FUZxxl

@FUZxxl: sous DosBox, cela fonctionne très bien même sans, mais dans ses sources, il est indiqué que les indicateurs sont préservés de tout ce qui se passait auparavant sous DOS et dans les TRS. Il serait donc probablement nécessaire de jouer prudemment. Quoi qu'il en soit, ce ne serait qu'un octet, le véritable avantage serait de tuer au moins un de ces gros (= 4 octets chacun) add/ sub.
Matteo Italia

Hm ... aucune idée, vraiment.
FUZxxl

Pouvez-vous changer loppour loop?
mbomb007

@ mbomb007: peut-être? Je ne suis pas sûr de ne pas faire la nasmdistinction entre loopune étiquette et une loopinstruction d'assemblage, aussi j'écris lopcomme tout le monde.
Matteo Italia

28

J, 32 28 octets

C'était amusant.

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

Explication

Voici comment cette solution fonctionne, y compris une explication de la manière dont elle a été jouée au 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
Très agréable! La solution est pleine de bonnes pièces!
randomra

1
(J'ajoute généralement un exemple d'invocation de la fonction pour que les utilisateurs non expérimentés puissent l'essayer également.)
randomra

Cette solution me fait mal à la tête:')
Nic Hartley

@QPaysTaxes Je considère cela comme un compliment.
FUZxxl

@FUZxxl C'est ça. C'est aussi un jeu de mots basé sur une séquence de caractères qui apparaît dans votre réponse.
Nic Hartley

15

C, 150 octets

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

C'était fou amusant de golf. Je ne suis toujours pas convaincu d'en avoir fini.

Nous définissons une fonction unique f, qui prend la chaîne en tant qu'entrée et les sorties sur stdout.

Passons en revue le code, ligne par ligne:

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

Je répondrai à toutes vos questions!

Essayez un programme de test en ligne !


Je tiens à rappeler que "char l = strlen (c) +1, o [l * l]" n'est pas valide car vous ne pouvez pas définir un tableau de taille variable comme celui-ci, mais cela fait 15 ans que je n'ai rien essayé de ce genre dans C.
Sparr

@Sparr Mon compilateur ne lance même pas d'avertissement. Je crois que c'était "officiellement" standard dans C99. Je vais essayer de trouver une référence pour cela.
BrainSteel

1
@Sparr Voici une référence.
BrainSteel

Merci. Il semble que les choses ont changé il y a environ 15 ans (à quelques reprises près) à cet égard :)
Sparr

1
@CoolGuy Il le ferait, mais lors des appels ultérieurs de f, mil ne serait pas réinitialisé à 0. Cela équivaut à "casser votre environnement", interdit ici .
BrainSteel

15

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

Cela utilise ANSI Escapes:

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

Équivalent à sed -e "s/(/(\\\e[B/g;s/)/\\\e[A)/g". Le \e[Bcode d'échappement signifie déplacer le curseur d'une rangée vers le bas et les \e[Amoyens de déplacer le curseur d'une rangée vers le haut. Cette solution insère donc simplement ces codes avant et après le début et la fin de chaque paire de parenthèses imbriquées. L'entrée est passée à travers STDIN.

Vous devrez l'appeler printf $(Retina ...)pour voir la sortie correctement.

Sortie

(((())))
(\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
Eh bien, pas mal! Si vous pouviez indiquer un terminal spécifique qui n'en a pas besoin, printfce serait formidable. Sinon, je pense qu'il serait juste d'ajouter | printfau nombre d'octets.
Martin Ender

@ MartinBüttner Il devrait être printf $()ou printf $(Retina ).
jimmy23013

1
Quelle est cette chose Retina?
FUZxxl

2
@FUZxxl C'est mon propre langage de programmation basé sur regex. Voir GitHub .
Martin Ender

2
Pourquoi \eplus printf? Vous pouvez simplement mettre les caractères de contrôle dans le modèle de remplacement.
Dennis

15

TI-BASIC, 69 60 56 55 octets

Ceci s’applique à la famille de calculatrices TI-83 + / 84 +, bien qu’elle ait été écrite sur une édition Silver 84+ C.

Le programme apparaît plus grand sur calcul en raison de la TVA et des informations de taille incluses. En outre, il y a plus de 56 caractères ici; 56 octets s'expliquent par le fait que toutes les commandes comportant plusieurs caractères sont compressées en jetons d'une taille égale à un ou deux octets.

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

Rasé un autre octet grâce à thomas-kwa ! (aussi de lui était le saut de 60 à 56.)


4
Ahhh, mon premier langage de programmation. Merci pour la nostalgie, haha.
Alex Pritchard le

1
Toujours en train de programmer des TI pour les cours de mathématiques au lycée, il est très utile de disposer de formules intégrées qui calculeront pour vous des tests et des devoirs.
Elias Benevedes

1
Si vous changez les choses, vous pouvez utiliser cette cos(piAnsastuce pour enregistrer un autre octet.
lirtosiast

9

Python 2, 115 octets

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)

Appelez comme f("((()())()(()(())()))"), et la sortie est sur STDOUT.

Explication

Nous commençons avec n = 0. Pour chaque caractère dans la ligne de saisie:

  • Si le caractère est (, nous ajoutons des nespaces puis des incrémentsn
  • Si le caractère est ), on décrémente npuis on ajoute des nespaces

Le résultat est ensuite compressé et imprimé. Notez que les zipzip de Python correspondent à la longueur de l' élément le plus court , par exemple

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

Habituellement, on utilisera itertools.zip_longest( izip_longest) s’ils veulent zippatiner à la longueur du plus long élément.

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

Mais dans Python 2, ce comportement peut être simulé en mappant None:

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

Python 3, 115 octets

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)

Pas Zipping, juste rembourrage appropriée avec ljust. Celui-ci semble avoir un potentiel de golf.


8

R, 151 127 caractères

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

Avec les retraits et les nouvelles lignes:

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

Usage:

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

Il lit la chaîne en tant que stdin, le divise en un vecteur de caractères simples, calcule la somme cumulée de (et ), soustrait le premier avec le dernier (avec un décalage), calculant ainsi le "niveau" de chaque parenthèse. Il imprime ensuite sur stdout, pour chaque niveau, les parenthèses correspondantes ou un espace.

Merci à @MickyT de m'avoir aidé à le réduire considérablement!


2
+1 solution agréable et élégante. Vous pouvez économiser 6 en remplaçant for(i in n)cat(ifelse(D[i]-j," ",S[i]));cat("\n")par X=S;X[which(D!=j)]=' ';cat(X,sep='',fill=T). Alors ce nn’est pas vraiment nécessaire, mais vous auriez besoin de changer un peu la partie Cumsum. D=c(C(S=="("),0)-c(0,C(S==")"));le ramenant à 135.
MickyT

@MickyT wow merci! n'a pas pensé à cela. whichn’est pas vraiment nécessaire ici ( D!=jétant déjà un vecteur de booléens permettant l’indexation). Je ne savais pas l' argument fillpour cat, c'est une bonne astuce! Merci de m'avoir fait raccourcir de 24 caractères!
Plannapus

8

C, 58 53 52 51 49 octets

Utilise les séquences d'échappement ANSI pour déplacer la position du curseur.

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

Si vous n'utilisez pas gcc ou un autre compilateur qui le supporte, \evous pouvez le remplacer par \x1B2 octets supplémentaires. \e[Adéplace le curseur d'une ligne vers le haut et \e[Bdéplace le curseur d'une ligne vers le bas. Il n'est pas nécessaire d'utiliser \e[Bpour descendre d'une ligne car il est plus court de deux octets pour utiliser le caractère de tabulation verticale ASCII 0xBou \v.

À partir de la question, la chaîne de saisie est supposée être composée uniquement de parenthèses (équilibrées). Par conséquent, vérifier la parité du caractère avec &1, suffit pour distinguer entre (et ).


7

Pip, 53 octets

Pépin est un langage de code-golf de mon invention. La première version a été publiée samedi, donc je peux officiellement la faire tourner! La solution ci-dessous n’est pas très compétitive en ce qui concerne les langues de golf, mais c’est en partie parce que je n’ai pas encore implémenté de fonctionnalités telles que zip et max.

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

Attend la chaîne de parenthèses en tant qu'argument de ligne de commande.

Version "non-golfée":

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

Explication:

Contrairement à la plupart des langages de golf, Pip est impératif avec les opérateurs infixes. La syntaxe est donc un peu plus proche de C et de ses dérivés. Il emprunte également des idées à la programmation fonctionnelle et basée sur les tableaux. Voir le référentiel pour plus de documentation.

Le programme génère d’abord une liste de profondeurs (en la stockant dans z) en mappant une fonction à la chaîne en entrée a. La variable globale vsuit le niveau actuel. (Les variables a-gdans Pip sont des variables de fonction locale, mais h-zglobales. vEst pratique car elle est préinitialisée à -1.)

Ensuite, nous utilisons une Wboucle hile pour générer et imprimer chaque ligne, jusqu'à ce que la ligne générée soit composée de tous les espaces. vest maintenant utilisé pour les colonnes et ipour les lignes. La {z@++v=i?as}fonction, mappée de manière répétée sur la chaîne d'entrée d'origine, teste si la ligne actuelle icorrespond à la ligne sur laquelle la parenthèse actuelle est supposée être activée (telle que stockée dans la zliste). Si c'est le cas, utilisez la parenthèse ( a); sinon, utilisez s(préinitialisé dans l'espace). Le résultat final est qu'à chaque itération, oune liste de caractères équivalente à la ligne suivante de la sortie est attribuée.

Pour vérifier si nous devons continuer à boucler, nous vérifions si, oavec tous les espaces RM, d est vide. Sinon, imprimez-le (par défaut, tout concatène comme dans CJam), réinitialisez le numéro de colonne sur -1 et incrémentez le numéro de ligne.

(Anecdote: au début, j'avais une solution de 51 octets ... qui n'a pas fonctionné, car un bug est apparu dans l'interpréteur.)


7

Pyth, 31 octets

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

Essayez-le en ligne.

-/<zk\(/<zhk\): Trouve le niveau approprié pour la position actuelle du personnage.

?YqN-/<zk\(/<zhk\)d: Un espace si le niveau approprié n'est pas le niveau actuel, le caractère actuel sinon.

Js.e?YqN-/<zk\(/<zhk\)dz: Générez la chaîne, enregistrez-la dans J.

I-JdJ: Si ce Jn'est pas tous les espaces, imprimez-le.

Vz: zTemps de boucle .


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/ \+$//'

Entrée / sortie via STDIN / STDOUT:

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

indentfait la plupart des tâches lourdes, mais doit travailler avec des attelles plutôt que des parens. Le reste est modification de cette réponse pour transposer la sortie 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 ligne par ligne. Pour un numéro de ligne donné i(en fait, sa négation), parcourt la chaîne d'entrée set crée une nouvelle chaîne zcontenant uniquement les caractères sat deep i. Ceci est fait en incrémentant ou décrémentant ipour suivre la profondeur actuelle, en ajoutant les caractères actuels lorsque iest 0ajusté pour le type de paren et en ajoutant un espace.

Ensuite, imprime et revient à la suivante isauf si la ligne en cours était composée d' espaces. Notez que, puisque les parens sont équilibrés, la iboucle après est identique à celle du début.

Python 3 serait identique sauf pour un personnage print(z).


5

La triche :( Retina + TeX, N octets tricherie :(

Cela ne fonctionne que si vous restituez (?) La sortie en utilisant MathJax ou un autre TeX, actuellement désactivé pour ce SE :(

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

Chaque ligne doit être dans un fichier différent, mais vous pouvez le tester en utilisant Retina -e "\(" -e "({" -e "\)" -e "})" -e "\{\(" -e "_{(" (ou la commande sed équivalente sed -e "s/(/({/g;s/)/})/g;s/{(/_{(/g"). L'entrée est passée à travers STDIN.

Cela fonctionne en entourant les contenus de chaque paire de parenthèses entre accolades, puis en indiquant tous les éléments qui les composent.

Sortie

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

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

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

Sortie TeX


1
Je suis flatté que vous ayez utilisé Retina, et c'est une bonne idée de sortir des sentiers battus, mais ce n'est pas tout à fait ce à quoi le résultat est censé ressembler. ;) Cela enfreint en particulier la formulation alternative "Une autre façon de voir les choses est que les parenthèses à la profondeur n sont déplacées vers la ligne n, tout en conservant leur position horizontale." Je serais très impressionné par une pure solution Retina règle conforme bien et peut - être distribuer une prime pour cela. ;)
Martin Ender

In total the lines must not be longer than twice the length of the input string. Changer la ligne 2 en (\,{et la ligne 4 en }\,)signifie que la sortie convient à cela (bien que la profondeur verticale soit toujours fausse: ()
user22723

Eh bien, j'ai réussi à faire une solution conforme à la règle
:)

1
Bon travail. Je suppose que cela signifie que vous pouvez supprimer la réponse trompeuse maintenant. ;)
Martin Ender

5

Java, 232 226 224 222 octets

Version golfée:

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

Version longue:

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 chaîne d'entrée est analysée en premier lieu, en recherchant "(" et ")" pour ajouter / soustraire un compteur et stocker sa valeur en déterminant la distance qui devrait séparer les parenthèses d'un tableau tout en gardant une trace de la profondeur du plus profond. Ensuite, le tableau est analysé. les parenthèses avec les valeurs les plus faibles sont imprimées en premier et continueront d’être imprimées ligne par ligne jusqu’à atteindre le maximum.

Je trouverai probablement des moyens de jouer au golf plus tard.


5

Javascript / ES6, 97 caractères

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

Usage

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

Explication

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

Au lieu de n<m?console.log(o):0, vous pouvez utiliser n<m&&console.log(o)ce qui enregistre 1 octet.
Ismael Miguel

4

CJam, 43 41 36 octets

Pas trop golfé (je pense), mais voici ma première tentative:

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

Comment ça fonctionne

J'utilise le fait très pratique que, )et (dans CJam, incrément et décrément signifient respectivement. Ainsi, j’évalue simplement les crochets pour obtenir la profondeur.

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

Essayez-le en ligne ici


4

Octave, 85 caractères

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

C'est une optimisation de l'approche naïve, ce qui est plutôt naturel pour Matlab et 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;

Il se t peut même que le tableau n'existe pas encore, et que nous puissions tout de suite attribuer un élément à un autre, et qu'il reprenne la dimension la plus petite requise pour que cet élément existe, ce qui est très pratique.


4

Perl, 91 89 88 84 80 79 octets

$t=<>;{$_=$t;s/\((?{$l++})|.(?{--$l})/$^R==$c?$&:$"/ge;print,++$c,redo if/\S/}
  • $ t est la chaîne d'entrée.
  • $ c est la profondeur que nous voulons imprimer sur la ligne en cours.
  • $ l est la profondeur à laquelle nous sommes après avoir rencontré un paren.
  • $ l est mis à jour dans des blocs de code incorporés regex .
  • $ ^ R est le résultat du bloc de code le plus récent.

4

Haskell, 154 octets

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

Même idée que l’autre solution Haskell, mais un peu plus courte. - utilisation:

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

3

J, 46

Pas aussi bien que les autres 'langues de golf', mais pour ma défense: J est terrible avec des cordes.

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

Prend la chaîne en tant qu'entrée pour une fonction. Il y a aussi probablement une meilleure façon de le faire dans J.

Usage:

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

Voir ma réponse pour une autre façon de procéder dans J.
FUZxxl

3
Personnellement, je pense que J convient parfaitement aux cordes. Vous avez juste besoin de penser avec des tableaux.
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]}}

Explication:

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

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

Dentelé:

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

Je suppose que la dernière boucle pourrait être raccourcie, mais je la laisserai comme un exercice au lecteur. ;-)


Vieux, 233 octets répondent:

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

Dentelé:

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

Je sais que cela fait plus d'un an, mais "je suppose que la dernière boucle pourrait être raccourcie, mais je la laisserai comme un exercice au lecteur. ;-)"; tu as vraiment raison. Il peut être changé de 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++]);pour -1 octet. En outre, vous pouvez enregistrer 2 octets supplémentaires en supprimant p=x=0et en utilisant simplement l' int p=0,x=0,initialisation des champs. Au total, il devient 211 octets .
Kevin Cruijssen

3

C #, 195 octets

Essayez d'abord de jouer au golf - criez si j'ai fait quelque chose de mal.

Version alternative C # utilisant SetCursorPosition et travaillant de gauche à droite en prenant l’entrée comme argument en ligne de commande.

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

Je pensais que ce serait amusant d’ajuster la position d’écriture en fonction du paren d’ouverture / fermeture et non de lignes complètes. Close paren déplace la position vers le haut avant d'écrire; open paren le baisse après avoir écrit. L'action SetCursorPosition enregistre cinq octets. Déplacer le curseur sur la ligne suivante après la sortie prendrait un peu plus.

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

Lot, 356 335 octets

Je sais qu'il existe déjà une solution Batch pour ce défi, mais celui-ci est beaucoup plus joué au golf et semble adopter une approche différente. Plus important encore, l’autre solution contient au moins une commande powershell; cette solution ne le fait pas.

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

Il y a un caractère de retour arrière ( U+0008) à l'avant-dernière ligne après le point (ligne 12, colonne 57). Ce n'est pas visible dans le code affiché ici, mais est inclus dans le nombre d'octets.


Quelqu'un d'autre soumet une réponse dans Batch - Nice one +1.
Unclemeat

3

Lot, 424 octets

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

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

Exemple:

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

3

C, 118 117 octets

Une autre réponse en C, mais la mienne est plus courte.

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

Version non-golfée:

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

Et il fonctionne!

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

1
Une solution assez élégante, cependant, putchar(c-d?32:*p)est un caractère plus court que putchar(c==d?*p:32).
pawel.boczarski

2

Haskell, 227 octets

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
Vous pouvez économiser quelques espaces avec des opérateurs: par exemple, n#[]au lieu de m n [].
Franky

2

Perl, 76 octets

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

Non use strictici :)


2

Lex, 94 octets

Dépend des codes de la console Linux. Avec gcc, vous pouvez supprimer quatre octets en remplaçant les deux instances \33par un caractère d'échappement réel.

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

Pour compiler et exécuter:

$ flex -o telescopic.c telescopic.l
$ gcc -o telecopic telescopic.c -lfl
$ ./telescopic
(()(()())()((())))(())
(                )(  )
 ()(    )()(    )  ()
    ()()    (  )
             ()
--- type ctrl-D ---
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.