Cuerdas topográficas

23

Aquí hay algunos ejemplos de entrada, así que puedo explicar cuál es el problema:

((1 2)(3 (4 5) moo)) (i (lik(cherries)e (woohoo)))

Piense en esta línea de texto como un mapa topográfico de algunas montañas. Cada conjunto de paréntesis ilustra una unidad de altitud.

Si "vemos" esto desde un lado, para que podamos ver las montañas verticalmente, veremos:

          4 5                cherries    woohoo  
  1 2  3       moo       lik          e
                      i

Dado uno de estos mapas topográficos, genera el mapa, pero en una escala vertical, como el resultado anterior. Separe los diferentes elementos en el mapa con el número de caracteres para el siguiente elemento. Por ejemplo, hay 4 espacios en la salida entre mooy i. Del mismo modo, hay 4 caracteres en la entrada entre mooy i.

El código que hace esto en la menor cantidad de caracteres gana.

beary605
fuente
¿Es seguro asumir que las alturas siempre serán positivas? Por ejemplo, la entrada ((1 2))))))))))3debe ser inválida si las alturas negativas están prohibidas.
Cristian Lupascu
@ w0lf: sí, los paréntesis siempre coincidirán.
beary605

Respuestas:

10

J, 87 79 72 70 67 57 56 caracteres

'( ) 'charsub|.|:(+/\@('('&=-')'&=)(],~' '$~[)"0])1!:1[1

Toma entrada del teclado. Ejemplo:

   '( ) 'charsub|.|:(+/\@('('&=-')'&=)(],~' '$~[)"0])1!:1[1
((1 2)(3 (4 5) moo)) (i (lik(cherries)e (woohoo)))
          4 5                cherries    woohoo
  1 2  3       moo       lik          e
                      i

Explicación:

Esta explicación se basa en la primera versión de mi programa:

|.|:('( ) 'charsub x)((' '$~{.@]),[{~{:@])"1(('('&([:+/=)-')'&([:+/=))\,.i.@#)x=.1!:1[1

x=.1!:1[1tomar entrada del teclado y ponerla xpara más tarde

(('('&([:+/=)-')'&([:+/=))\,.i.@#)crea una lista de todas las indeces en la cadena ( i.@#) y las ,.une ( ) junto con el resultado del (('('&([:+/=)-')'&([:+/=))\verbo.

(('('&([:+/=)-')'&([:+/=))\este verbo se aplica a todos los prefijos de la cadena (por lo que en la entrada hellose aplicaría a h, he, hel, hell, y hello. Se trata de un tenedor , que cuenta el número de tramos abiertos ('('&([:+/=)y luego se resta el número de tramos estrechos ')'&([:+/=). Esto me da la lista de indeces en la cadena y el nivel en el que el carácter en ese índice debe estar en la salida. En una entrada simple esto me da lo siguiente:

   (('('&([:+/=)-')'&([:+/=))\,.i.@#)x=.1!:1[1
(one(two(three)))
1  0
1  1
1  2
1  3
2  4
2  5
2  6
2  7
3  8
3  9
3 10
3 11
3 12
3 13
2 14
1 15
0 16

((' '$~{.@]),[{~{:@])"1Este es un verbo que toma la lista que acabo de generar y también la salida de ('( ) 'charsub x)(que solo reemplaza una cadena para reemplazar todos los corchetes con espacios x). Toma la cola de cada elemento de la lista {:@]y lo usa como índice en la cadena para obtener el carácter [{~{:@]. Luego lo antepone ,con el número de espacios como lo indica el encabezado de cada elemento en la lista (' '$~{.@]). En el ejemplo anterior esto me da:

   ('( ) 'charsub x)((' '$~{.@]),[{~{:@])"1(('('&([:+/=)-')'&([:+/=))\,.i.@#)x=.1!:1[1
(one(two(three)))

 o
 n
 e

  t
  w
  o

   t
   h
   r
   e
   e

Luego transpongo la matriz |:y la invierto |.para obtener la salida deseada.

Gareth
fuente
6

GolfScript 69

0:§;{.'()'?))3%(.§+:§' ':s*\@s\if\n}%n/.{,}%$)\;:μ;{.,μ\-s*\+}%zip n*

Demostración en línea aquí .

Explicación:

0:§;                # declare the variable §, representing the 
                    # current vertical level and initialize it at 0

{                   # iterate for each char in the string:

    .'()'?))3% (    # add on the stack the amount by which
                    # the current vertical level should be 
                    # adjusted:
                    #   * +1 if the character is '('
                    #   * -1 if the character is ')'
                    #   * 0 otherwise

    .§+:§           # adjust the value of §

    ' ':s*          # add as many spaces as § tells us
                    # and save the space in variable s

    \@s\if\         # return current char, if it's printable,
                    # or a space if it's '(' or ')'

    n               # add a newline char

}%

n/                  # split by newline char; now we have 
                    # an array of strings on the stack.
                    # Each string is a vertical line of the
                    # final output.

.{,}%$)\;:μ;        # Iterate through the strings and find the
                    # maximum length

{
    .,μ\-s*\+       # Add spaces at the end to make all the strings 
                    # the same length
}%

zip                 # Transpose the strings

n*                  # Join the transposed strings by newline characters
Cristian Lupascu
fuente
@Gareth Sí, ambos lo hacemos :)
Cristian Lupascu
¿Le gustaría agregar una explicación de cómo funciona?
Timwi
@Timwi He editado mi respuesta para incluir una explicación
Cristian Lupascu
5

APL (59)

⊖↑{⊃,/T\¨⍨⍵×P=0}¨R∘=¨(⍴T)∘⍴¨⍳⌈/R←1++\P←+/¨1 ¯1∘ר'()'∘=¨T←⍞

He asumido que la 'base' también debe ser utilizable. ( (a(b))c(d)es decir, es válido) Si esto no es necesario, se pueden guardar dos caracteres.

Explicación:

  • T←⍞: almacena una línea de entrada en T
  • '()'∘=¨T: para cada carácter en T, vea si es un paréntesis de apertura o cierre. Esto proporciona una lista de listas de booleanos.
  • 1 ¯1∘ר: multiplique el segundo elemento en cada una de estas listas por -1 (entonces un paréntesis de apertura es 1, uno de cierre es -1 y cualquier otro carácter es 0).
  • +/¨: toma la suma de cada lista interna. Ahora tenemos el valor ∆y para cada personaje.
  • P←: tienda en P.
  • R←1++\P: toma un total acumulado de P, dando la altura de cada personaje. Agregue uno a cada carácter para que los caracteres fuera de los paréntesis estén en la primera línea.
  • (⍴T)∘⍴¨⍳⌈/R: para cada valor de y posible, haga una lista siempre que T, que consista solo en ese valor. (es decir, 1111 ..., 2222 ...., etc.)
  • R∘=¨: para cada elemento en esta lista, vea si es igual a R. (Para cada nivel, ahora tenemos una lista de ceros y unos correspondientes a si un personaje debe aparecer o no en ese nivel).
  • ⍵×P=0: para cada una de estas listas, ajústelo a cero si P no es cero en ese punto. Esto elimina los caracteres con un delta-y distinto de cero, por lo que elimina los paréntesis.
  • ⊃,/T\¨⍨: para cada profundidad, seleccione de T los caracteres que deben aparecer.
  • ⊖↑: crea una matriz y ponla al derecho.
marinus
fuente
¿Qué implementación de APL estás usando? ¿Es gratis?
FUZxxl
@FUZxxl He estado usando Dyalog APL, la versión de Windows se puede descargar de forma gratuita.
marinus
5

Tcl, 50

puts \33\[9A[string map {( \33\[A ) \33\[B} $argv]

Tipo de trampa, pero bueno ...

Utilizo secuencias de escape ascii para obtener la diferencia de línea, ^[[Asignifica mover el cursor 1 línea hacia arriba, ^[[Bmover el cursor 1 línea hacia abajo.

Johannes Kuhn
fuente
5

APL, 41 caracteres / bytes *

{⊖⍉⊃(↑∘''¨-⌿+/¨p∘.=,\⍵),¨⍵/⍨1-2×⍵∊p←'()'}

Probado en Dyalog, con un ⎕IO←1y ⎕ML←3entorno. Es una función que toma la entrada requerida y devuelve la salida. Dada la redacción de la pregunta, creo que es aceptable. En caso de que no sea así, aquí hay una versión que lee de stdin y escribe en stdout, por 4 caracteres más:

⍞←⊖⍉⊃(↑∘''¨-⌿+/¨'()'∘.=,\a),¨a/⍨1-2×'()'∊⍨a←⍞

Explicacion :

{                                 p←'()'}  p is the string made of two parentheses
                                ⍵∊ ______  check which characters from ⍵ are parens
                            1-2× ________  -1 for every par., 1 for every other char
                         ⍵/⍨ ____________  replace () with spaces in the orig. string
    (                 ),¨ _______________  append every char to the following items
                   ,\⍵ _____________________  for every prefix of the original string
               p∘.= ________________________  check which chars are '(' and which ')'
            +/¨ ____________________________  sum: compute the number of '(' and ')'
          -⌿ _______________________________  subtract the no. of ')' from that of '('
     ↑∘''¨ _________________________________  generate as many spaces as that number
 ⊖⍉⊃ ____________________________________  make it into a table, transpose and flip

Ejemplos:

topo '((1 2)(3 (4 5) moo)) (i (lik(cherries)e (woohoo)))'
          4 5                cherries    woohoo   
  1 2  3       moo       lik          e           
                      i                           

 

topo 'a  (  b ( c(d)e ) f  )  g'
            d            
          c   e          
      b           f      
a                       g

*: APL se puede guardar en una variedad de caracteres heredados de un solo byte que asignan símbolos APL a los 128 bytes superiores. Por lo tanto, para jugar al golf, un programa que solo usa caracteres ASCII y símbolos APL puede puntuarse como caracteres = bytes.

Tobia
fuente
Estoy buscando el juego de caracteres APL aquí y no puedo encontrar el símbolo. Parece una combinación de los caracteres ¨y ~?
Gareth
Hola @Gareth No, no estaba en IBM APL2. Puede encontrarlo en Dyalog (comercial, pero hay una versión de nagware enterrada en su sitio web, y eso es lo suficientemente bueno para jugar al golf; en mi humilde opinión, la mejor APL disponible en la actualidad), Nars2000 (la mejor APL de código abierto), GNU APL y la APL de ngn , entre otros.
Tobia
@Gareth Gráficamente es la combinación de ~y ¨, aunque es un personaje diferente de ambos. Es un operador llamado Commute . En su forma diádica que voltea los argumentos de la función diádica que se aplica a: (5-2)=(2-⍨5). Como operador monádico se convierte en una función diádica monádico, duplicando el argumento de la derecha: (2*2)=(*⍨2). Se usa principalmente para escribir una secuencia ininterrumpida de funciones de derecha a izquierda, sin tener que poner paréntesis en torno a expresiones grandes y saltar los ojos alrededor de ellas. En golf es útil porque 3*⍨1-2es un char menos que (1-2)*3:-)
Tobia
2
Entonces es el equivalente de ~en J entonces.
Gareth
3

J, 56 caracteres

'( ) 'charsub|.|:((,~#&' ')"0[:+/\1 _1 0{~'()'&i.)1!:1]1

Otra solución J de 56 personajes ... Me cuenta la profundidad traduciendo (en ⁻1, )en 1 y todos los demás caracteres en 0, y luego tomando la suma acumulada de esto: [: +/\ 1 _1 0 {~ '()'&i.. El resto es en gran medida similar a la solución de @ Gareth.

Luciérnaga
fuente
2

Python, 161 caracteres

S=raw_input()
R=range(len(S))
H=[S[:i].count('(')-S[:i].count(')')for i in R]+[0]
for h in range(max(H),0,-1):print''.join((' '+S[i])[H[i]==H[i+1]==h]for i in R)
Keith Randall
fuente
2

Python, 130

a=[""]*9
l=8
i=0
for c in raw_input():o=l;l+=c==')';l-=c=='(';a[l]=a[l].ljust(i)+c*(o==l);i+=1
print"\n".join(filter(str.strip,a))
grc
fuente
2

Rubí 1.9 (129)

Lecturas de stdin.

l=0
$><<gets.split('').map{|c|x=[?(]*99;x[l+=c==?(?-1:c==?)?1:0]=c;x}.transpose.map(&:join).*(?\n).tr('()',' ').gsub(/^\s+\n/,'')
Paul Prestidge
fuente
3
¡Agradable! descubriste un error en el marcador Ruby :)
Cristian Lupascu
He probado y el resaltado SQL funciona mejor para su programa.
Cristian Lupascu
@ w0lf ha, tienes razón. He cambiado la //a ''la que mantiene el carácter recuento de la misma y evita el fallo en el marcador.
Paul Prestidge
2

C, 132 caracteres

char*p,b[999];n;
main(m){for(p=gets(memset(b,32,999));*p;++p)*p-41?*p-40?p[n*99]=*p:++n>m?m=n:0:--n;
for(;m;puts(b+m--*99))p[m*99]=0;}

La descripción no especificó la cantidad de información que el envío tenía que aceptar para ser aceptado, por lo que decidí establecer límites que fueran más consistentes con mis necesidades de golf (mientras seguía trabajando con la entrada de ejemplo dada). Permítanme aprovechar esta oportunidad para recordarles a las personas que a menudo es una buena idea especificar máximos mínimos en las descripciones de sus desafíos.

Hay dos bucles principales en el código. El primer ciclo agrupa todos los caracteres que no son paréntesis en la línea de salida apropiada, y el segundo ciclo imprime cada línea.

caja de pan
fuente
1

C, 149 caracteres

#define S for(i=0;c=v[1][i++];)h+=a=c-'('?c-')'?0:-1:1,
c,i,h=0,m=0;main(int a,char**v){S m=h>m?h:m;for(;m;m--){S putchar(a||h-m?32:c);putchar(10);}}

ejecutar con el argumento citado, egaout "((1 2) (3 (4 5) moo)) (i (lik (cerezas) e (woohoo)))"

conejo bebé
fuente
0

Octava, 128

Muy similar a mi última respuesta ...

p=1;x=[0];y=input(0);for j=1:numel(y);p-=(y(j)==")");x(p,j)=y(j);p+=(y(j)=="(");end;x(x==40)=x(x==41)=x(x==0)=32;char(flipud(x))

Prueba

Entrada: "((1 2)(3 (4 5) moo)) (i (lik(cherries)e (woohoo)))"

Salida:

          4 5 cerezas woohoo   
  1 2 3 moo lik e           
                      yo                           
sudo rm -rf slash
fuente
0

C #, 229 bytes

Si no hay restricciones en el espacio vertical inicial, puede usar esto (sangrado para mayor claridad). Inicializará el cursor una línea por cada (encontrado antes de imprimir, luego moverá el cursor hacia arriba y hacia abajo a medida que se leen los corchetes.

using C=System.Console;
class P{
    static void Main(string[]a){
        int l=a[0].Length,i=l;
        while(i>0)
            if(a[0][--i]=='(')C.CursorTop++;
        while(++i<l){
            char c=a[0][i];
            if(c=='('){
                c=' ';
                C.CursorTop--;
            }
            if(c==')'){
                c=' ';
                C.CursorTop++;
            }
            C.Write(c);
        }
    }
}
Hand-E-Food
fuente
0

PowerShell , 120 119 bytes

(($h=($c=$args|% t*y)|%{($l+=(1,-1)[$_-40])})|sort)[-1]..0|%{$x=0;$y=$_
-join($c|%{"$_ "[$h[$x++]-ne$y-or$_-in40,41]})}

Pruébalo en línea!

Efectos secundarios: caracteres &y 'cambios de altura como (y ), pero se muestran. Comparar resultados para:

&$f "((1 2)(3 (4 5) moo)) (i (lik(cherries)e (woohoo)))"
&$f "&&1 2'&3 &4 5' moo'' &i &lik&cherries'e &woohoo'''"

Menos golfizado:

$chars=$args|% toCharArray

$heights=$chars|%{
    $level+=(1,-1)[$_-40]       # 40 is ASCII for '(', 41 is ASCII for ')'
    $level
}

$maxHeight=($heights|sort)[-1]

$maxHeight..0|%{
    $x=0;$y=$_
    $line=$chars|%{
        "$_ "[$heights[$x++]-ne$y -or $_-in40,41]
    }
    -join($line)
}
mazzy
fuente
-1

VB.net (para S&G)

No es el código más bonito.

Module Q
 Sub Main(a As String())
  Dim t = a(0)
  Dim h = 0
  For Each m In (From G In (t.Select(Function(c)
                                     h += If(c = "(", 1, If(c = ")", -1, 0))
                                     Return h
                                   End Function).Select(Function(y, i) New With {.y = y, .i = i}))
             Group By G.y Into Group
             Order By   y Descending
            Select Group.ToDictionary(Function(x) x.i)
               ).Select(Function(d) New String(
                          t.Select(Function(c,i)If(d.ContainsKey(i),If(c="("c Or c=")"c," "c,c)," "c)).ToArray))
   Console.WriteLine(m)
  Next
 End Sub
End Module
Adam Speight
fuente