* Sobrescribir * etiquetas

23

Si alguna vez ha intentado agregar etiquetas a una trama realmente densa, se dará cuenta de que a veces las etiquetas se superponen entre sí, lo que las hace difíciles de leer. Vamos a hacer algo similar pero en 1D.

La entrada será una secuencia de (label, x-coordinate)pares, y la salida será el resultado de dibujar cada punto y etiqueta, en el orden dado. Se *debe colocar un asterisco que represente el punto en la coordenada x dada y la etiqueta debe seguir. Los caracteres existentes se sobrescribirán.

Por ejemplo, si la entrada fue

Hello  0
World  8
Fizz   3
Buzz   5
PPCG   16
X      9

Entonces sucedería lo siguiente:

*Hello
*Hello  *World
*He*Fizz*World
*He*F*Buzzorld
*He*F*Buzzorld  *PPCG  
*He*F*Buz*Xrld  *PPCG

La línea final se debe generar.

Reglas de E / S

  • La entrada puede consistir en cualquier número de pares. Cada etiqueta constará solo de letras mayúsculas y minúsculas, y las longitudes de las etiquetas serán como máximo 127 caracteres. Cada coordenada x estará entre 0 y 127 inclusive.

  • La entrada puede estar en cualquier lista conveniente o formato de cadena de manera que los pares no sean ambiguos y las etiquetas / coordenadas x se alternen en la entrada. Por ejemplo, un formato como [("Hello", 0), ("World", 8) ...]o [0 "Hello" 8 "World" ...]está bien. Sin embargo, no puede suponer dos listas separadas de etiquetas y coordenadas x.

  • Las funciones y los programas completos están bien.

  • Cualquier punto no cubierto por una etiqueta debe representarse con un espacio. Sin embargo, puede que no haya ningún espacio en blanco inicial o posterior ajeno a una sola línea final opcional.

Ejemplos

Entrada:

OneLabel   10

Salida:

          *OneLabel

Entrada:

Heathrow   0
Edinburgh  2
London     4
Liverpool  6
Oxford     8

Salida:

*H*E*L*L*Oxfordl

Entrada:

alpha     20
beta       4
gamma     57
delta      3
epsilon   22
zeta      32
eta       53
theta     27

Salida:

   *delta           *a*epsi*thetazeta                *eta*gamma

Entrada:

abc  5
d    5
abc  10
ABCDEFGHIJKLMNOPQRSTUVWXYZ 127

Salida:

     *dbc *abc                                                                                                                 *ABCDEFGHIJKLMNOPQRSTUVWXYZ

Tenga en cuenta que las etiquetas y / o las coordenadas x pueden repetirse.

Sp3000
fuente
Si las coordenadas x son [0,127] y las cadenas son (0,127], ¿puede una etiqueta salir del extremo derecho de la línea, o está protegida? Es decir, "foo 127" finaliza la línea con "*" o ? "* foo" Sólo comprobar si la cadena debe tener un final suave o duro.
PotatoOmeletteSandwich
3
@PotatoOmeletteSandwich Mi intención era que la longitud total se ajustara dentro de 255, por lo que la longitud máxima de salida se producirá cuando haya una etiqueta de longitud 127 en la coordenada x 127. La salida final no debe truncarse de ninguna manera, excepto para eliminar los espacios en blanco finales .
Sp3000

Respuestas:

7

CJam, 24 23 19 bytes

l~Sf.*'*f*:.{S^+1=}

Esto lee la entrada como una matriz CJam de pares de coordenadas-etiqueta.

Pruebe este violín en el intérprete de CJam o verifique todos los casos de prueba a la vez.

¡Gracias a @ MartinBüttner por ayudarme a ahorrar 4 bytes!

Cómo funciona

l~                   Read a line from STDIN and evaluate it.
  Sf                 For each pair, push the pair and " "; then:
    .*                 Perform vectorized repetition.
                         [X "label"] " " .* -> [(X spaces) "label"]
      '*f*           Join each resulting pair, using '*' as separator.
          :.{     }  Reduce by the following vectorized operator:
                       Push two characters (A and B).
             S^        Compute the symmetric difference of B and " ".
                       This pushes "B " for a non-space B and "" otherwise.
                +1=    Append and select the second character (with wrap).
                       This selects B for "AB " and A for "A".
Dennis
fuente
2
Acabo de agregar un caso de prueba y pensé que dejaría un comentario diciendo que no, que no rompió esta sumisión: la interpretación del intérprete de CJam solo se traduce en palabras. Por si alguien se confunde.
Sp3000
4

Pyth, 20 bytes

V.Tmrj" *"d9Qpe+d-Nd

Pruébelo en línea: Demostración o conjunto de pruebas

Explicación

V.Tmrj" *"d9Qpe+d-Nd
   m        Q         map each pair d of the input to:
     j" *"d             join d by the string " *"
    r      9            range-length encode 
                        (this gives x-coordinate spaces, a star and the label)
 .T                   transpose this table 
V                     for N in ^:
                 -Nd    remove spaces from N
               +d       add a space at the beginning
              e         take the last character
             p          and print it (without newline)
Jakube
fuente
1
Esto es mucho mejor que lo que tenía.
isaacg
4

JavaScript ES6, 104 bytes

c=>(a=Array(255).fill(" "))&&c.map(([u,v])=>a.splice(u,v.length+1,..."*"+v))&&a.join``.replace(/ +$/,"")

Ejemplo de uso

Entrada en una consola compatible:

t = [[0,"Hello"],[8,"World"],[3,"Fizz"],[5,"Buzz"],[16,"PPCG"],[9,"X"]];
(c=>(a=Array(255).fill(" "))&&c.map(([u,v])=>a.splice(u,v.length+1,..."*"+v))&&a.join``.replace(/ +$/,""))(t);

Salida de la última declaración:

"*He*F*Buz*Xrld  *PPCG"

Explicación

Esto crea una función anónima de ctres expresiones que se han unido lógicamente. Las dos primeras afirmaciones son siempre verdaderas, y las reglas de cortocircuito de JS dicen que siempre que la primera sea verdadera, devuelva el valor completo en el lado derecho (sin coaccionar a booleano): entonces esto es formalmente equivalente a

(function (c) {
    a = Array(255).fill(" ");                    // global variable `a` overwritten
    c.map(function (x) {                         // only side-effects are used here.
       var u = x[0], v = x[1];                   // ES6 destructuring
       a.splice(u, v.length + 1, ..."*" + v));   // main logic
    });
    return a.join("").replace(/ +$/, "");        // postprocessing and trim
})

La primera declaración tiene que estar entre paréntesis arriba porque el operador de asignación =tiene menor prioridad que el operador lógico AND &&.

El ensamblaje "parámetro de reposo" ..."*"+vtambién es parte de ES6; concatena un líder *a la cadena y luego lo interpreta como un parámetro similar a una lista, dividiéndolo en un grupo de argumentos que se proporcionan Array.prototype.splice, que toma (m, n, ...rest)y modifica su matriz en la posición mpara eliminar nelementos y luego inserta todos los restargumentos. Para lograr esto antes de ES6, usaría los más engorrosos:

[].slice.apply(a, [u, v.length + 1].concat(("*" + v).split("")))

La matriz se concatena con la cadena vacía y se elimina el espacio en blanco al final.

CR Drost
fuente
4

Python 2, 67 bytes

z=''
for a,b in input():z=(z+' '*b)[:b]+'*'+a+z[len(a)-~b:]
print z

Toma como entrada [('Heathrow', 0), ('Edinburgh', 2), ('London', 4), ('Liverpool', 6), ('Oxford', 8)]e imprime el resultado.

Python no permite que se modifiquen las cadenas, y la conversión hacia y desde una lista es costosa. Entonces, esto recrea la cadena zpara agregar una nueva palabra. Tomamos los bcaracteres antes de la palabra, rellenando con espacios si es necesario, luego el nuevo texto con un asterisco, luego la parte zdespués de la nueva palabra. Tenga en cuenta que los espacios finales nunca se agregan.

La reduceversión es 3 caracteres más larga (70):

lambda I:reduce(lambda z,(a,b):(z+' '*b)[:b]+'*'+a+z[len(a)-~b:],I,"")
xnor
fuente
3

Ruby, 94 81 75 bytes

Golfizado:

s=" "*128;$<.map{|l|w,p=l.split;p=p.to_i;s[p..w.size+p]="*"+w};$><<s.rstrip

Aquí está el código sin golf:

s = " "*128
$<.map{|l|                 # for each line entered via stdin, ctrl+D to stop
  w,p = l.split            # had to move the chomp down here
  p = p.to_i               # there's no 'to_i!'...
  s[p..w.size+p] = "*"+w   # in the range of *foobar, replace the string
}
$><<s.rstrip               # output suggested by w0lf

¡Gracias @ w0lf por las sugerencias sobre la asignación de la entrada!

Gracias @ w0lf y @Not que Charles por la idea de eliminar una variable.

PatataOmeletteSandwich
fuente
Vea los consejos de golf de Ruby . En este caso, podría aplicar el $ <. Map {| l | ...} es más corto que mientras l = gets; ...; end tip y probablemente reemplace puts con $><<(lo que no requiere espacio extra).
Cristian Lupascu
Además, creo que .chompse puede eliminar.
Cristian Lupascu
En este caso, ahora que lo mencionas, creo que es muy seguro eliminarlo, ya que .to_ieso lo atrapará. Buen pensamiento. Gracias @ w0lf!
PotatoOmeletteSandwich
¡De nada! Aquí hay una versión más corta en la que apliqué los consejos anteriores y algunos más: ideone.com/BiOvV5 . Siéntete libre de publicarlo en tu respuesta.
Cristian Lupascu
3
@PotatoOmeletteSandwich Actualiza tu Ruby. 1.8.7 está al final de la vida! Además, debe poder utilizar el s[int, int]formulario en lugar de s[range]ahorrar 1 char.
No es que Charles
3

Javascript 121 caracteres

Usando características no estándar, funciona en Firefox.
x=Array(255).fill(" ");eval(prompt()).map(s=>{s[0].split``.map((n,i)=>x[s[1]+i+1]=n);x[s[1]]="*"});x=x.join``.trimRight()

Versión antigua: x=Array(255).fill(" ");eval(prompt()).map(s=>{s[0].split``.map((n,i)=>x[s[1]+i+1]=n);x[s[1]]="*"});x=x.join``.replace(/ +$/,"")

x=Array(255).fill(" ");      //Creates an array with spaces
eval(prompt())               //Gets some input, has to look like [["Hello",4],["Hi",14],["Oi",0]]
.map(s=>{s[0].split``.map((n,i)=>x[s[1]+i+1]=n);x[s[1]]="*"}); //Main "logic"
x=x.join``.replace(/ +$/,"") //Gets rid of the trailing spaces
Stefnotch
fuente
1
/ +/ tiene mucho más sentido que \sdecepcionado ¡Me lo perdí! ¿Podría guardar bytes usando x=' '.repeat(255);y evitando .join?
Dom Hastings
1
@DomHastings: las cadenas JS son inmutables, por lo que tendrías que .split('')hacerlo en una estructura de datos mutable, pero en ese punto Array(255).fill(' ')es más corto. En mi versión, la mayoría de mis ahorros provienen de (a) usar la regla "puede dar una función o programa" para eliminar eval(prompt())a cambio de c=> y (b) usar el Array.prototype.slicemétodo incorporado con un parámetro de descanso para acortar un poco la parte lógica .
CR Drost
1
@ ChrisDrost ah, por supuesto ... ¡Olvidé que es solo un accesorio! La vergüenza [].map.call(s[0],tampoco guarda nada ...
Dom Hastings
2

Python, 85 bytes

def g(p):
 z=[' ']*256
 for a,b in p:z[b:b+len(a)+1]='*'+a
 return''.join(z).rstrip()

Pruébalo en línea

Mego
fuente
1
Debería poder hacer 'z'[2::5](backticks en lugar de apóstrofes) en lugar de ''.join(z)guardar un byte, y moverse z=[' ']*256a los parámetros debería guardar otro. Además, creo que puedes cambiar returna print.
Kade
Creo que puede guardar caracteres escribiendo un programa con p=input()(Python 2) en lugar de una función, lo que evita la sangría. Además, b+len(a)+1puede serb-~len(a)
xnor
1
En realidad, un programa simplemente te permite hacerlo for a,b in input():.
xnor
2

Perl, 66 bytes

Script de 63 bytes + 3 bytes para -p

$}||=$"x128;/\s+/,substr$},$',1+length$`,"*$`"}{$_=$};s/\s+$/
/

Nada muy especial, utilizando las variables $`y$' que son 'antes del partido' y 'después del partido' respectivamente, en lugar de dividir la cadena. Usé un $}para la variable de cadena ya que originalmente me estaba ahorrando un byte, ¡pero ya no lo es!

Ejemplo de ejecución:

$perl -p overwritlabels.pl <<< 'Hello  0
World  8
Fizz   3
Buzz   5
PPCG   16
X      9'
*He*F*Buz*Xrld  *PPCG

Perl, 65 bytes

Script de 62 bytes + 3 bytes para -p

Otra versión que imprime cada línea (¡por un byte menos!). (Sí, hice esto porque no leí la pregunta correctamente ...)

$}||=$"x128;/\s+/;substr$},$',1+length$`,"*$`";$_=$};s/\s+$/
/

Ejemplo de ejecución:

$perl -p overwritlabels.pl <<< 'Hello  0
World  8
Fizz   3
Buzz   5
PPCG   16
X      9'
*Hello
*Hello  *World
*He*Fizz*World
*He*F*Buzzorld
*He*F*Buzzorld  *PPCG
*He*F*Buz*Xrld  *PPCG
Dom Hastings
fuente
2

PHP - 84 bytes

<? foreach(array_chunk(array_slice($argv,1),2) as $p) echo "␣[".($p[1]+1)."G*$p[0]";
                                                            ^ ESC character (\x1b)

Utiliza códigos de escape ANSI para colocar el cursor ( \x1b[XGcon el carácter Escape y X como la coordenada basada en 1), seguido de la *cadena de entrada para esa fila. Acepta entradas en la línea de comando del formulario:

php filename.php Heathrow 0 Edinburgh 2 London 4 Liverpool 6 Oxford 8
php filename.php abc 5 d 5 abc 10 ABCDEFGHIJKLMNOPQRSTUVWXYZ 127

Acepta entradas de varias palabras si están entre comillas, ya que son argumentos de línea de comandos.

Niet the Dark Absol
fuente
1

C ++ 11, 95 bytes

Por qué no?

Como una función, reciba la entrada como un map<int, string>nombre que vcontiene la posición y la cadena.

string t(255,' ');for(auto&m:v){int i=m.first;t[i++]='*';for(auto&c:m.second)t[i++]=c;}cout<<t;

Uso

#include <iostream>
#include <map>
using namespace std;
int main(){
    map<int,string> v{{0,"Heathrow"},{2,"Edinburgh"},{4,"London"},{6,"Liverpool"},{8,"Oxford"}};
    string t(255,' ');for(auto&m:v){int i=m.first;t[i++]='*';for(auto&c:m.second)t[i++]=c;}cout<<t;
}

Compruébalo corriendo aquí

Wendelbsilva
fuente