¡Dios mío, está cubierto de pestañas!

26

¡Usuarios de sangría espacial, uníos ! ¡Debemos luchar contra todos los usuarios humildes !

Tu misión (si eliges aceptarla) es escribir un programa o función que tome dos argumentos:

  • Una cadena: esta es la entrada.
  • Un entero positivo: este es el número de espacios por pestaña.

Debe pasar por cada línea de la cadena y reemplazar cada pestaña utilizada para la sangría con el número dado de espacios, y cada pestaña no utilizada para la sangría (por ejemplo, en el medio de una línea) con un espacio.

Tenga en cuenta que las líneas como \t \tabcson comportamiento no definido; fueron insertados por los usuarios malvados de la pestaña para complicar sus programas.

De acuerdo con la Sociedad Tabs Must Die, su programa debe ser lo más breve posible para evitar que los usuarios malvados lo detecten.

Ejemplo

\t se usa para representar pestañas aquí.

Cadena de entrada:

a
\t\tb\tc
d

Número de entrada:

4

Salida:

a
        b c
d

La línea media estaba sangrada por 8 espacios, 4 por pestaña (ya que el número dado era 4).

Cadena de entrada:

\ta\t\tb

Número de entrada:

4

Salida:

    a  b

NOTA: Esto no es un duplicado del desafío de expansión de pestañas ; requiere un formato de entrada muy diferente y requisitos ligeramente diferentes.

kirbyfan64sos
fuente
1
, siempre y cuando la pregunta no solicite explícitamente números decimales (que no lo hace).
Martin Ender
2
posible duplicado de pestañas Expandir (implementar expandir (1))
Ismael Miguel
1
¿Podemos suponer que la entrada contiene solo ASCII imprimible, pestañas y líneas nuevas?
Dennis
2
Caso de prueba propuesto: \ta\t\tb, 4(mi revisión anterior estaba fallando que uno)
Dennis
2
Necesitamos una respuesta en espacios en blanco.
Kaz Wolfe

Respuestas:

7

CJam, 30 24 23 bytes

q{_9=NA=Seasi*' ?@?:N}/

Normalmente me niego a publicar código malicioso en Internet ...

Este es un programa completo que lee la cadena de STDIN y el número como un argumento de línea de comandos.

Pruébelo en línea en el intérprete de CJam .

Cómo funciona

q                        Read all input from STDIN.
 {                   }/  For each character C in the input:
  _9=                      Push 1 if C is a tab and 0 otherwise.
     NA=                   See below.
        Seasi*             Push a string of W spaces, where W is the integer from
                           the command-line arguments.
              '            Push a spaces character.
                ?          Select the string if NA= pushed a truthy value, the
                           single space otherwise.
                 @         Rotate C on top of the stack.
                  ?        Select the string of spaces or the single space if _9=
                           pushed 1, the character C otherwise.
                   :N      Save the result in N.

Que NA=hace:

  • Para el primer carácter, Ncontendrá su valor predeterminado, es decir, la cadena "\n".

    Para todos los caracteres posteriores, Ncontendrá el resultado de la última iteración, es decir, el último carácter de entrada, un carácter de espacio o una cadena de uno o más espacios.

  • Si Nes una cadena, NA=selecciona el elemento en el índice 10 de N (ajuste). El resultado será un espacio o un carácter de salto de línea. Ambos son sinceros.

    Si N es un personaje, NA=presiona 1 para un salto de línea y 0 en caso contrario.

  • Debido a lo anterior, NA=empujará un valor verdadero para el primer carácter, un carácter precedido por un salto de línea o un carácter precedido por una cadena de espacios (sangría que ya ha sido reemplazada).

    En todos los demás casos (incluido un tabulador que ha sido reemplazado por un carácter de espacio ), NA=generará un valor falso.

Dennis
fuente
66
Lo bueno es que estás haciendo un servicio en Internet al eliminar pestañas maliciosas. ;)
Alex A.
19

K5, 53 45 bytes

{{,/(b+a&~b:x*&\a:9=y){$[x;x#" ";y]}'y}[x]'y}

En acción:

  {{,/(b+a&~b:x*&\a:9=y){$[x;x#" ";y]}'y}[x]'y}[4;(,"a";"\t\tb\tc";,"d")]
(,"a"
 "        b c"
 ,"d")

Solo quiero que el registro muestre que esta pregunta es moralmente reprobable.

JohnE
fuente
11
-21346106841 para... this question is morally reprehensible.
TheNumberOne
3
Esto debe terminar siendo la respuesta más votada, simplemente para que la gente vea la nota al pie.
Geobits
Puede devolver el resultado en lugar de imprimirlo por 3 bytes.
kirbyfan64sos
1
@ kirbyfan64sos: estoy imprimiendo el resultado para evitar tener que unir las líneas. Si puedo aceptar y devolver el resultado como una lista de cadenas, una para cada línea, podría guardar `0:y "" \ n "\`.
JohnE
@JohnE No puse una regla que diga que no puedes, así que supongo que puedes. :)
kirbyfan64sos
8

Perl, 23 bytes

Código de 22 bytes + línea de comando de 1 bytes

¡Esperemos que no sea demasiado descarado para asumir que la entrada numérica se puede dar a través del parámetro -i! Asegúrese de reemplazar \ t en el siguiente código con el carácter de tabulación real.

s/\G\t/$"x$^I/ge;y/\t/ /

Ejemplo de uso:

printf "a\n\t\tb\tc\nd" | perl -p entry.pl -i4

O por conveniencia:

printf "a\n\t\tb\tc\nd" | perl -pe 's/\G\t/$"x$^I/ge;y/\t/ /' -i4

Explicación:

El uso del -pargumento ejecutará el programa para cada línea en la entrada, luego imprimirá el resultado al final.

En el ejemplo anterior, la sustitución de expresiones regulares reemplaza \G\tcon " "x4(un espacio repetido cuatro veces). \Ges una construcción de expresiones regulares poco conocida que coincide con la posición de la primera coincidencia si es la primera iteración, o desde la posición de la coincidencia anterior si no es la primera iteración, lo que significa que solo reemplazará todas las pestañas al comienzo de la cadena, y hazlo uno por uno. El y/\t/ /simplemente reemplaza todas las pestañas restantes con espacios.

Jarmex
fuente
2

Julia, 69 59 bytes

f(s,n)=(r=replace)(r(s,r"^\t*"m,i->" "^endof(i)n),"\t"," ")

Sin golf:

function f(s::String, n::Int)
    # Replace the leading indentation tabs
    r1 = replace(s, r"^\t*"m, i -> " "^endof(i)n)

    # Replace any remaining tabs between words
    r2 = replace(r1, r"\t", " ")

    # Return
    r2
end

¡Ahorré 10 bytes y solucioné un problema gracias a Glen O!

Alex A.
fuente
¿Hay algún beneficio en reemplazar las pestañas de sangría principales por separado? Me parece que debería ser manejado directamente por la parte de "pestañas restantes". Además, su parte "reemplazar las pestañas entre texto" solo coincidirá con una sola pestaña, ¿qué pasa si tiene "hello\t\t1"?
Glen O
Si suponemos que toda la sangría se realiza con pestañas (sin "\t \t"situaciones), podría hacer esto:, f(s,n)=(r=replace)(r(s,r"^\t*"m,i->" "^endof(i)n),"\t"," ")que utiliza una función de reemplazo y capturará todas las pestañas de sangría en un solo golpe.
Glen O
@GlenO Wow, eso es realmente genial. ¡Muchas gracias!
Alex A.
Noté que mi respuesta fue rechazada. ¿Hay algo que haya hecho mal? Estaré encantado de abordar cualquier problema.
Alex A.
No veo ningún problema ¿Tal vez es solo uno de esos tipos vengativos que votan negativamente porque no les gusta un idioma o cosas así? No puedo ver ningún defecto.
Glen O
2

Haskell, 82 bytes

n!('\t':x)=([1..n]>>" ")++n!x
n!x=f<$>x
f '\t'=' '
f x=x
g n=unlines.map(n!).lines

Entonces g 3 "a\n\t\tb\tc\nd"hace la cosa.

Lynn
fuente
2

Mathematica, 42 37 bytes

Gracias a @ LegionMammal978 por múltiples sugerencias para guardar código. El primer parámetro, #es para el texto de entrada, el segundo parámetro,, #2para el número de espacios por pestaña.

StringReplace[#,"\t"->" "~Table~{#2}]&
DavidC
fuente
Además, puede cambiar Table[" ",{#2}]a " "~Table~{#2}para guardar un byte. ¿Por qué estás StringJoinponiendo la cadena vacía en él?
LegionMammal978
1

Ruby 49 bytes

def r s,t;s.gsub! /^\t/,' '*t;s.gsub!"\t",' ';end
MegaTom
fuente
2
Esto no funciona si hay dos pestañas al comienzo de una línea.
No es que Charles
1

JavaScript (ES6), 70

Usando cadenas de plantilla, la nueva línea es significativa y contada

(s,n,r=n)=>[...s].map(c=>c<`
`?` `.repeat(r):(r=c<` `?n:1,c)).join``

Pruebe a ejecutar el fragmento a continuación en Firefox.

F=(s,n,r=n)=>[...s].map(c=>c<`
`?` `.repeat(r):(r=c<` `?n:1,c)).join``

// TEST
out=x=>O.innerHTML+=x+'\n\n'

out('Input: "A\\n\\t\\tB\\tC\\nD" 4\nOutput:\n'+F('A\n\t\tB\tC\nD',4))

out('Input: "\\tA\\t\\tB" 4\nOutput:\n'+F('\tA\t\tB', 4))
<pre id=O></pre>

edc65
fuente
1
¡Vaya un voto negativo! ¿Podría ser alguien que no puede leer o entender 'Prueba en Firefox'?
edc65
Sospecho sesgo de idioma. Julia y CJam también recibieron votos negativos.
Dennis
1

CoffeeScript, 72 bytes

(s,n)->s.replace(/^\t+/mg,(m)->" ".repeat(m.length*n)).replace /\t/g," "

(Intentando jugar golf al menos 2 mordidas más, por lo que superará la solución ES6 ... Ayuda apreciada: D)

Uso:

f=(s,n)->s.replace(/^\t+/mg,(m)->" ".repeat(m.length*n)).replace /\t/g," "
str="""
My nice\tString
\tIndent <--
\t\tDouble
""" #\t is recognized as tab by CS
alert(f(str,4))
Bojidar Marinov
fuente
1

Retina, 42 bytes

Todas las apariciones de .son espacios, todas \tson pestañas literales (1 byte) y <empty>representa un archivo en blanco. Es solo por legibilidad. Tampoco estoy completamente seguro de que estoy haciendo el bucle correctamente, pero creo que sí. Cada línea debe colocarse en su propio archivo. Agregué 1 byte por cada archivo adicional.

Se supone que la entrada está en Unary en su propia línea al final de la entrada.

(1*)$
_$1
m+`(?<!^|\t)\t
.
(`1$
<empty>
)`\t
\t.
\t|_
<empty>

Explicación

Agrego un _ antes de la entrada Unary para delimitarlo durante el reemplazo, de modo que no elimine ninguno de la cadena de entrada. Luego, reemplazo todas las pestañas no al comienzo de una línea con un solo espacio. Luego, hago un bucle, eliminando un solo 1y agregando un solo espacio después de cada pestaña, hasta que me quedo sin entrada. Finalmente, limpio quitando las pestañas y el subrayado.

mbomb007
fuente
1

Python, 72 68 bytes

Las pestañas son pestañas literales (1 byte), por r'...'lo que no es necesario. Desafortunadamente, Python requiere look-behinds / look-aheads de "ancho fijo", por lo que no puedo usarlos (?<!^|\t). Utiliza prácticamente el mismo método que mi solución Retina.

import re
lambda s,n:re.sub('\t',' '*n,re.sub('(?<!^)(?<!\t)\t',' ',s))
mbomb007
fuente
1

Stax , 20 bytes

ÜR╧█╧╫≡eX,)~σOÜ¢G╩N‼

Ejecutar y depurarlo

Este programa lee la primera línea como el ancho de la sangría y el resto de la entrada como el programa.

recursivo
fuente
0

Haskell , 75 bytes

s#m|let('\t':r)#n=(' '<$[1..n])++r#n;(x:r)#n=x:r#(m^sum[1|x<' ']);e#_=e=s#m

Pruébalo en línea!Esto supone que la entrada contiene solo caracteres imprimibles, así como pestañas y líneas nuevas, según lo permitido por OP en los comentarios.

Explicación:

La #función externa toma una cadena sy un número my llama a la función interna definida localmente #con los mismos argumentos. Esto se hace para realizar un seguimiento del mvalor original , ya que la #función interna cambia el número:

  • ('\t':r)#n=(' '<$[1..n])++r#nSi encuentra una pestaña, reemplácela por nespacios y no la cambie n.
  • (x:r)#n=x:r#(m^sum[1|x<' '])Si se encuentra algo xque no es una pestaña, manténgalo como está pero establezca nel número original msi xes una nueva línea y de lo 1contrario. Esto se hace mediante m^sum[1|x<' ']: mse lleva a la potencia de la sum[1|x<' ']cual se evalúa 1cuando xes más pequeño que un espacio (es decir, una nueva línea), por lo que obtenemos m^1 = m. De lo contrario es 0y tenemos m^0 = 1.
Laikoni
fuente
0

Java 11, 134 bytes

n->s->{var r="";for(var p:s.split("\n")){for(;p.charAt(0)==9;p=p.substring(1))r+=" ".repeat(n);r+=p+"\n";}return r.replace('\t',' ');}

Pruébalo en línea.
NOTA: Java 11 aún no está en TIO, por lo que " ".repeat(n)se ha emulado comorepeat(" ",n) lugar (con el mismo número de bytes).

Explicación:

n->s->{                 // Method with integer & String parameters and String return-type
  var r="";             //  Result-String, starting empty
  for(var p:s.split("\n")){
                        //  Loop over the rows (split by new-lines)
    for(;p.charAt(0)==9;//   Inner loop as long as the current row starts with a tab
       p=p.substring(1))//     After every iteration: remove the first character (tab)
      r+=" ".repeat(n); //    Append `n` amount of spaces to the result-String
    r+=p+"\n";}         //   Append the rest of the row with a newline to the result
  return r.replace('\t',' ');} 
                        //   Replace any remaining tabs with a space, and return the result
Kevin Cruijssen
fuente