Expandir pestañas (implementar expandir (1))

10

Esta vez, su tarea es implementar una variante de la expand(1)utilidad POSIX que expande las pestañas a los espacios.

Su programa debe tomar una especificación de tabulación y luego leer la entrada en el estándar y reemplazar los caracteres de tabulación en la entrada con la cantidad adecuada de espacios para llegar a la siguiente tabulación. El resultado debe escribirse al estándar .

Especificación Tabstop

Una especificación de tabulación consta de un número único o una lista de tabulaciones separada por comas. En el caso de un número único, se repite como si se produjeran múltiplos en una lista separada por comas (es decir, 4actúa como 4,8,12,16,20,...). Cada entrada en una lista separada por comas es un entero positivo opcionalmente prefijado por a +. Un +prefijo indica una diferencia relativa con el valor anterior en la lista separada por comas. El primer valor en la lista debe ser absoluto (es decir, sin prefijo). Los tabuladores especifican la columna del siguiente carácter sin espacio (siguiendo la pestaña expandida), con la columna más a la izquierda tomada como el número 0. Los tabuladores siempre deben expandirse al menos a un espacio.

De entrada y salida

La especificación de tabulación debe tomarse como el primer parámetro de línea de comando para el programa, o leerse desde el estándar como la primera línea de entrada (terminada por una nueva línea), a su discreción. Después de que se haya leído la tabulación, la entrada restante (toda la entrada, en el caso anterior) hasta que EOF se procese y expanda. La salida expandida se escribirá en salida estándar.

Se supone que todas las pestañas expandidas y todas las entradas tienen un máximo de 80 columnas de ancho. Todas las pestañas expandidas están aumentando estrictamente.


Ejemplo

La especificación Tabstop 4,6,+2,+8es equivalente a 4,6,8,16, y con ambas entradas

ab<Tab>c
<Tab><Tab>d<Tab>e<Tab>f

se expande en ( indica un espacio)

ab␣␣c
␣␣␣␣␣␣d␣e␣␣␣␣␣␣␣f

01234567890123456   (Ruler for the above, not part of the output)
          1111111

La puntuación es puro ; el código más corto gana.

Luciérnaga
fuente

Respuestas:

2

GolfScript ( 77 75 caracteres)

n/(','/{'+'/{~t++}*~:t}%81,{t*}%+:T;{[0\{.9={;T{1$>}?(.)@-' '*}*\)}/;]n+}/;

Estoy bastante satisfecho con el análisis de tabspec.

# Split on commas
','/
# For each element:
{
    # Split on '+'
    '+'/
    # We now have either ["val"] or ["" "val"]
    # The clever bit: fold
    # Folding a block over a one-element array gives that element, so ["val"] => "val"
    # Folding a block over a two-element array puts both elements on the stack and executes,
    # so ["" "val"]{~t++}* evaluates as
    #     "" "val" ~t++
    # which evaluates val, adds the previous value, and concatenates with that empty string
    {~t++}*
    # Either way we now have a string containing one value. Eval it and assign to t
    ~:t
}%

Luego agrego múltiplos del último elemento hasta que se garantice que tengo suficiente para llegar al final de las 80 columnas:

81,{t*}%+

Esto proporciona el comportamiento deseado cuando solo se especificó una parada de pestañas, y de lo contrario solo es relevante en casos que la especificación no menciona. (Nota: hace que la lista de tabulaciones vuelva a 0 y luego repita el último elemento analizado, pero eso es irrelevante porque cuando se trata de usar la lista busco el primer elemento mayor que la posición actual).

El resto es bastante sencillo.

Peter Taylor
fuente
2

Rubí 161 145

Lee la especificación de tabulación en la primera línea de entrada.

i=t=[]
gets.scan(/(\+)?(\d+)/){t<<i=$2.to_i+($1?i:0)}
81.times{|j|t<<j*i}
while gets
$_.sub!$&," "*(t.find{|s|s>i=$`.size}-i)while~/\t/
print
end

editar: se agregaron dos líneas que hacen que la última lectura de tabulación se repita para que las especificaciones de tabulación de un solo número también funcionen correctamente

ies una variable temporal para mantener la última tabulación analizada. tes la lista de tabulaciones, analizada desde la gets.scanlínea. Por si acaso, agregamos 81 múltiplos de la última tabulación analizada. el while getsbucle continúa hasta que no haya más entradas. Para cada línea de entrada, sustituimos las pestañas por espacios, una pestaña a la vez porque la cadena se mueve a medida que agregamos los espacios y debemos volver a calcular la detención de pestañas correcta.

daniero
fuente
Realmente no conozco a Ruby, pero ¿puedes escribir x+($1?i:0)como el más corto $1?x+i:x?
Timwi
@Timwi Nope! Ruby es un poco extraño con el operador ternario. Por lo general, debe colocar un espacio allí en algún lugar, porque los dos puntos ( :) también pueden marcar el comienzo de un símbolo , pero dado que un símbolo no puede comenzar con un dígito, :0está bien sin espacio. O algo. Es raro. Los paréntesis son cruciales también parece.
daniero
Ese escaneo de pestañas me parece defectuoso. En t<<x+($1?i:0);i=xla primera declaración no cambia x, ¿verdad? Creo que debes revertirlo comoi=x+($1?i:0);t<<i
Peter Taylor
1
De hecho, puede guardar 16 reemplazando las dos primeras líneas con i=t=[](ya que ise garantiza que no será necesario la primera vez); simplificando el análisis tab-stop {t<<i=$2.to_i+($1?i:0)}y eliminando por lcompleto ( iya tiene ese valor). Pero bueno, no preocuparse por que la pestaña deje de aumentar estrictamente: eso le ahorra 4 caracteres, y puedo pedirlo prestado para ahorrar 2.
Peter Taylor
@PeterTaylor ¡Gracias por el aporte! No fue directamente con errores, pero ciertamente un poco hinchado. Me resulta demasiado fácil quedarse ciego en un código como este.
daniero
1

C, 228 caracteres

Aquí hay una solución C para comenzar las cosas. Todavía hay mucho golf por hacer aquí (mira todos esos ifs y fors y putchars ...). Probado con el ejemplo de caso de prueba, así como con la misma entrada pero 4y 8para la pestaña de especificaciones.

S[99],i;L,C;main(v){for(v=1;v;)v=scanf("+%d",&C),v=v>0?C+=L:scanf("%d",&C),
v&&(S[L=C]=++i,getchar());for(;i==1&&C<80;)S[C+=L]=1;for(C=L=0;C=~getchar();)
if(C+10)putchar(~C),L+=C+11?1:-L;else for(putchar(32);!S[++L];)putchar(32);}
Luciérnaga
fuente