Romper pestañas por la mitad

31

Las guerras santas se han librado por espacios frente a pestañas. (Y, por supuesto, los espacios, siendo objetivamente superiores, ganaron). Alex A.

S ome PEO p le todavía se niegan a un ccept que WHI c h es Cl e arly es UPREME. Acaba de recibir un archivo mediante el incor re ct, b anuncio, y inf e forma rior del WHI t Espace, y ahora t que le cont e NTS del archivo de un r e contaminada y arruinado.

Usted decide que también podría mostrarle a la persona que le envió el archivo lo equivocada que está, violentamente.

Descripción

Como sugiere el título, su desafío es tomar un archivo que contenga una o más pestañas:

this is an evil tab    onoes

y los destroza despiadadamente:

this is an evil tab

                     o
                     n
                     o
                     e
                     s

Tenga en cuenta que el software Stack Exchange convierte las pestañas literales en cuatro espacios (porque es correcto), por lo que las pestañas dentro de esta publicación se mostrarán como cuatro espacios. La entrada a su programa, sin embargo, contendrá pestañas reales.

Reto

La solución debe tomar una sola cadena como entrada, que puede contener ASCII imprimible, nuevas líneas y pestañas. Siempre habrá al menos una sola pestaña en la entrada.

El resultado debe ser la misma cadena, con las siguientes reglas aplicadas:

  • Inicie el cursor en las coordenadas (0,0) y con una dirección hacia la derecha. Las coordenadas son (columna, fila), indexadas a cero, y la dirección es en qué dirección debe mover el cursor después de imprimir un carácter.

  • Para cada carácter en la cadena:

    • Si es una nueva línea, muévase a las coordenadas (0, n), donde n es el número de nuevas líneas en la cadena hasta el momento (incluida esta), y restablezca la dirección a la derecha.

    • Si se trata de una pestaña, genera dos espacios, gira la dirección del cursor 90 grados en el sentido de las agujas del reloj y genera dos espacios más, efectivamente "dividiendo" la pestaña por la mitad. Aquí hay un ejemplo visual, donde una pestaña se representa como --->y espacios como ·:

      foo--->bar--->baz
      

      se convierte

      foo···
           ·
           b
           a
           r
           ·
           ·
       zab··
      
    • De lo contrario, simplemente muestre el carácter en el cursor y mueva el cursor un paso en la dirección actual.

Como está leyendo la cadena de principio a fin, es posible que tenga que escribir "encima" de los caracteres existentes, esto está bien. Por ejemplo, la entrada

foo--->bar


spaces are superior

debería dar como resultado una salida de

foo

     b
spaces are superior
     r

Puede elegir si las "pestañas rotas" deberían sobrescribir otros caracteres; la intención original era que no lo hicieran, pero la especificación era ambigua, por lo que esta es su decisión.

Además, después de aplicar estas reglas, también puede

  • agregue o elimine tantos espacios finales como desee.

  • agregue un máximo de una nueva línea final.

La entrada nunca contendrá espacios finales; nunca contendrá nuevas líneas iniciales o finales. También puede suponer siempre que nunca necesitará escribir en una columna o fila inferior a 0 (es decir, fuera de la pantalla).

Caso de prueba

Las pestañas en este caso de prueba se representan como --->porque, de lo contrario, SE las engulle.

Entrada:

Test case. Here's a tab--->there's a tab--->everywhere a tab--->tab--->this is some more text
blah
blah
blah blah blah blah blah blah--->blaah--->blaah--->blah--->blaaaaah--->blah--->blah--->blah--->blah--->blah

Salida:

Test case. Here's a tab
blah
blah                     t
blah blah blah blah blah blah
                        blaablah
                         r     b
                         e     l  b
                      h  'h    a  l
                      a  sa    a  a
                      l   l    h  h
       this is some mobe tbxt

                         haalhalb
     b                   a
     a                   b
     t

        bat a erehwyreve

Animación de lujo:

Reglas

  • Este es el , por lo que el código más corto en bytes ganará.
Pomo de la puerta
fuente
Cuando dice que el cursor tiene que comenzar en (0,0)¿quiere decir que necesitamos limpiar la consola primero, o simplemente quiere decir con eso la posición predeterminada del cursor?
Martin Ender
18
Estoy votando para cerrar esta pregunta como fuera de tema porque está llena de odio y blasfemia.
aditsu
1
Su animación se parece tanto al intérprete> <> que ahora quiero ver una entrada auto modificable> <>.
Sanchises
1
Me gustó el mensaje oculto en el párrafo inicial pero tengo que estar en desacuerdo.
wf4
@ MartinBüttner Eso solo significa la posición predeterminada.
Pomo de la puerta

Respuestas:

8

MATLAB, 144 bytes

El arma de elección para manejar cadenas es, por supuesto, un lenguaje diseñado para manipular números [cita requerida]. Bromas aparte, lo mejor de Matlab es que no le importa si asigna a una matriz 'fuera de límites': simplemente hará una matriz más grande. Además, el elemento de matriz predeterminado 0, se representa como un espacio en lugar de un nullcarácter que prescribe la especificación ASCII.

Las pestañas son simplemente un salto en las coordenadas, por lo que no se generan espacios para una pestaña.

function o=q(t)
u=2;v=0;x=1;y=1;n=1;for s=t
if s==9 x=x+u-v;y=y+v+u;a=v;v=u;u=-a;elseif s<11
n=n+1;x=1;y=n;else
o(y,x)=s;x=x+u/2;y=y+v/2;end
end

Comencé con 209 bytes, pero un golf más cuidadoso eliminó la mayor parte de eso; Hay muchas repeticiones en este código, así que hice algunas pruebas y errores que alternativas funcionaron mejor. No creo que haya mucho espacio para una mayor optimización con este código, pero siempre estoy feliz de que se demuestre lo contrario. Editar: Tom Carpenter logró demostrarme que estaba equivocado; se las arregló para guardar 9 bytes que optimicé para guardar la friolera de 29 bytes. Último byte guardado asumiendo que no hay caracteres de control (ASCII <9) en la entrada: las cadenas MATLAB no están nullterminadas.

Sanchises
fuente
No parece funcionar Intenté esto q('hello<tab>my name<tab>is tom<tab>c'), pero es algo parecido a Attempted to access o(11,-2); on line 7. Aunque esto puede tener más que ver con un problema en la pregunta, si el cursor se dirige hacia atrás y va más allá de la primera columna, ¿qué sucede con el resto de la línea?
Tom Carpenter
Sí, mi mal me perdí ese bit. Me iré ahora;)
Tom Carpenter
1
Puede guardar otros 9 caracteres eliminando la dvariable y en su lugar tener 4 variables que para que un bucle haga el patrón [1 0 -1 0] como tal: function o=q(t) u=1;v=0;w=-1;z=0;x=0;y=1;n=1;for s=t if s==9 x=x+2*u-2*v;y=y+2*v+2*u;a=z;z=w;w=v;v=u;u=a;elseif s==10 n=n+1;x=0;y=n;else x=x+u;y=y+v;o(y,x)=s;end end (obviamente, en los comentarios eliminó todas las líneas, por lo que tendrá para reformatearlo como el tuyo para ver lo que hice)
Tom Carpenter
@TomCarpenter Eso es ... realmente feo. Me encanta.
Sanchises
5

Python 3, 272 270 266 262 255 253 244 bytes

I=[]
try:
 while 1:I+=[input()]
except:r=m=0
M=sum(map(len,I))
O=[M*[' ']for _ in[0]*M]
for l in I:
 x=b=0;y=r;a=1;r+=1
 for c in l:
  if'\t'==c:a,b=-b,a;x+=a+2*b;y+=b-2*a
  else:O[y][x]=c
  x+=a;y+=b;m=max(m,y)
for l in O[:m+1]:print(*l,sep='')

El \tdebería ser un tabulador real.

El código funciona de manera similar a la respuesta de Zach Gates, generando primero una cuadrícula Mpor Mdonde Mes la suma de las longitudes de las líneas. (Eso es una gran cantidad de exceso, pero hace que el código sea más corto). Luego recorre los caracteres, colocándolos en los lugares correctos, haciendo un seguimiento de la fila visitada más inferior. Finalmente, imprime todas las líneas hasta esa fila.

La salida contiene (generalmente una gran cantidad de) espacios finales y 1 nueva línea final.

PurkkaKoodari
fuente
3

Javascript (ES6), 264 245 bytes

Intenté el enfoque "crear una cuadrícula gigante de espacios, rellenar y recortar", que terminó 19 bytes más corto que el otro.

a=t=>(o=`${' '.repeat(l=t.length)}
`.repeat(l).split`
`.map(q=>q.split``),d=x=y=z=0,s=c=>o[d>2?y--:d==1?y++:y][d?d==2?x--:x:x++]=c,[...t].map(c=>c=='\t'?(s` `,s` `,++d,d%=4,s` `,s` `):c==`
`?(x=d=0,y=++z):s(c)),o.map(p=>p.join``).join`
`.trim())

Al modificar la penúltima línea de esta manera, puede eliminar la gran cantidad de espacios finales en cada línea:

...o.map(p=>p.join``.trimRight())...

Pruébalo aquí:

Explicación próximamente; sugerencias bienvenidas!

ETHproducciones
fuente
3

JavaScript (ES6), 180183

Usando cadenas de plantilla, hay algunas nuevas líneas que son significativas y contadas.

Esa es una función que devuelve el resultado solicitado (rellenado con toneladas de espacios finales)

Hay poco que explicar: las filas se construyen según sea necesario. No hay una variable de dirección, solo el desplazamiento 2 para x e y, ya que en la rotación en el sentido de las agujas del reloj se manejan fácilmente:dx <= -dy, dy <= dx

Prueba a ejecutar el fragmento a continuación en Firefox

f=s=>[...s].map(c=>c<`
`?(x+=2*(d-e),y+=2*(e+d),[d,e]=[-e,d]):c<' '?(y=++r,e=x=0,d=1):(t=[...(o[y]||'')+' '.repeat(x)],t[x]=c,o[y]=t.join``,x+=d,y+=e),o=[r=x=y=e=0],d=1)&&o.join`
`

// TEST  

// Avoid evil tabs even in this source 
O.innerHTML = f(`Test case. Here's a tab--->there's a tab--->everywhere a tab--->tab--->this is some more text
blah
blah
blah blah blah blah blah blah--->blaah--->blaah--->blah--->blaaaaah--->blah--->blah--->blah--->blah--->blah`
 .replace(/--->/g,'\t'))
<pre id=O></pre>

edc65
fuente
Ojalá todos los idiomas tuvieran [x, y] = [expr1, expr2] ...
Sanchises
1

Python 2, 370 369 368 bytes

Gracias a @sanchises y @ edc65 por guardarme un byte cada uno.

J=''.join
u=raw_input().replace('\t','  \t  ')
w=u[:]
G=range(len(u))
d,r=0,[[' 'for _ in G]for _ in G]
u=u.split('\n')
for t in G:
 x,y=0,0+t
 for c in u[t]:
  if c=='\t':d=(d+1)%4
  if c!='\t':
   if c.strip():r[y][x]=c
   if d<1:x+=1
   if d==1:y+=1
   if d==2:x-=1
   if d>2:y-=1
r=r[:max(i for i,n in enumerate(r)if J(n).strip())+1]
for i in r:print J(i).rstrip()

Genera la cuadrícula más grande posible y luego recorre, carácter por carácter, cambiando de dirección en cada pestaña.

Puertas de Zach
fuente
Sugerencia: if !dyif d>2
Sanchises
!dNo es una sintaxis válida. @sanchises Gracias por el d>2consejo, sin embargo.
Zach Gates
Lo siento, en realidad no sé Python :) Simplemente asumí que funcionaría así.
Sanchises
Yo tampoco entiendo Python, pero si d en 0 ... 3, d==0->d<1
edc65
Sí, tienes razón. Gracias por el byte. @ edc65
Zach Gates