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[1
tomar entrada del teclado y ponerla x
para 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 hello
se 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
((' '$~{.@]),[{~{:@])"1
Este 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.
((1 2))))))))))3
debe ser inválida si las alturas negativas están prohibidas.