* Substituir * etiquetas

23

Se você já tentou adicionar rótulos a uma plotagem realmente densa, perceberá que às vezes os rótulos se sobrepõem, dificultando a leitura. Nós vamos fazer algo semelhante, mas em 1D.

A entrada será uma sequência de (label, x-coordinate)pares e a saída será o resultado do desenho de cada ponto e etiqueta, na ordem especificada. Um asterisco *representando o ponto deve ser colocado na coordenada x fornecida e o rótulo deve seguir. Quaisquer caracteres existentes serão substituídos.

Por exemplo, se a entrada foi

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

Então o seguinte aconteceria:

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

A linha final deve então ser impressa.

Regras de E / S

  • A entrada pode consistir em qualquer número de pares. Cada etiqueta consiste apenas em letras maiúsculas e minúsculas e os comprimentos das etiquetas terão no máximo 127 caracteres. Cada coordenada x estará entre 0 e 127, inclusive.

  • A entrada pode estar em qualquer formato conveniente de lista ou string, de modo que os pares sejam inequívocos e os rótulos / coordenadas x se alternem na entrada. Por exemplo, um formato como [("Hello", 0), ("World", 8) ...]ou [0 "Hello" 8 "World" ...]está bom. No entanto, você não pode assumir duas listas separadas de rótulos e coordenadas x.

  • Funções e programas completos estão bem.

  • Quaisquer pontos não cobertos por uma etiqueta devem ser representados com um espaço. No entanto, pode não haver nenhum espaço em branco inicial ou final estranho além de uma única nova linha final opcional.

Exemplos

Entrada:

OneLabel   10

Saída:

          *OneLabel

Entrada:

Heathrow   0
Edinburgh  2
London     4
Liverpool  6
Oxford     8

Saída:

*H*E*L*L*Oxfordl

Entrada:

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

Saída:

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

Entrada:

abc  5
d    5
abc  10
ABCDEFGHIJKLMNOPQRSTUVWXYZ 127

Saída:

     *dbc *abc                                                                                                                 *ABCDEFGHIJKLMNOPQRSTUVWXYZ

Observe que etiquetas e / ou coordenadas x podem ser repetidas.

Sp3000
fonte
Se as cordas x são [0,127] e as seqüências de caracteres são (0,127], um rótulo pode ser executado na extremidade direita da linha ou está protegido? Ou seja, "foo 127" termina a linha com "*" ou "* foo"? Apenas verificando se a string deve ter um final suave ou difícil.
PotatoOmeletteSandwich
3
@PotatoOmeletteSandwich Minha intenção era que o comprimento total caiba dentro de 255, para que o comprimento máximo de saída ocorra quando houver um rótulo de comprimento 127 na coordenada x 127. A saída final não deve ser truncada de forma alguma, exceto para remover o espaço em branco à direita .
SP3000

Respostas:

7

CJam, 24 23 19 bytes

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

Isso lê a entrada como uma matriz CJam de pares de rótulos de coordenadas.

Experimente este violino no intérprete CJam ou verifique todos os casos de teste de uma só vez.

Obrigado a @ MartinBüttner por me ajudar a economizar 4 bytes!

Como 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
fonte
2
Acabei de adicionar um caso de teste e pensei em deixar um comentário dizendo que não, não quebrou essa submissão - o intérprete de CJam produz apenas palavras. Apenas no caso de alguém ficar confuso.
SP3000
4

Pitão, 20 bytes

V.Tmrj" *"d9Qpe+d-Nd

Experimente on-line: Demonstration or Test Suite

Explicação

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
fonte
1
Isso é muito melhor do que o que eu tinha.
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(/ +$/,"")

Exemplo de uso

Entrada em um console compatível:

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);

Saída da última instrução:

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

Explicação

Isso cria uma função anônima de caté três expressões que foram AND logicamente juntas. As duas primeiras instruções são sempre verdadeiras, e as regras de curto-circuito do JS dizem que sempre que a primeira for verdadeira, retorne todo o valor no lado direito (sem coagir ao booleano): portanto, isso é 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
})

A primeira instrução deve ser colocada entre parênteses acima, porque o operador de atribuição =tem precedência mais baixa que o operador AND lógico &&.

O conjunto "resto do parâmetro" ..."*"+vtambém faz parte do ES6; concatena uma liderança *à string e, em seguida, interpreta-a como um parâmetro semelhante a uma lista, dividindo-a em vários argumentos fornecidos Array.prototype.splice, que pegam (m, n, ...rest)e modificam sua matriz na posição mpara remover nelementos e depois inserir todos os restargumentos. Para fazer isso antes do ES6, você usaria o mais complicado:

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

A matriz é concatenada com a sequência vazia e o espaço em branco à direita é excluído.

CR Drost
fonte
4

Python 2, 67 bytes

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

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

O Python não permite que strings sejam modificadas, e a conversão de e para uma lista é cara. Portanto, isso recria a string zpara adicionar uma nova palavra. Pegamos os bcaracteres antes da palavra, preenchendo espaços, se necessário, depois o novo texto com um asterisco e depois a parte zapós a nova palavra. Observe que os espaços finais nunca são adicionados.

A reduceversão tem 3 caracteres a mais (70):

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

Ruby, 94 81 75 bytes

Golfe:

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

Aqui está o código não destruído:

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

Obrigado @ w0lf pelas sugestões sobre o mapeamento da entrada!

Obrigado @ w0lf e @Não Charles pelo pensamento em remover uma variável.

BatataOmeletaSandwich
fonte
Veja as dicas de golfe para Ruby . Nesse caso, você pode aplicar o $ <. Map {| l | ...} é mais curto do que enquanto l = obtém; ...; extremidade final e provavelmente substitui puts por $><<(que não requer espaço extra).
Cristian Lupascu 19/10/2015
Além disso, acho que .chomppode ser removido.
Cristian Lupascu 19/10/2015
Nesse caso, agora que você mencionou, é provável que seja muito seguro removê-lo, como .to_iserá o caso. Bom pensamento. Obrigado @ w0lf!
PotatoOmeletteSandwich
De nada! Aqui está uma versão mais curta na qual apliquei as dicas acima e mais algumas: ideone.com/BiOvV5 . Sinta-se à vontade para publicá-lo em sua resposta, se quiser.
Cristian Lupascu 19/10/2015
3
@PotatoOmeletteSandwich Atualize seu Ruby. 1.8.7 é final de vida! Além disso, você poderá usar o s[int, int]formulário em vez de s[range]economizar 1 char.
Não que Charles,
3

Javascript 121 caracteres

Usando recursos não padrão, funciona no 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()

Versão antiga: 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
fonte
1
/ +/ faz muito mais sentido do que \sdecepcionar, eu perdi isso! Você poderia salvar bytes usando x=' '.repeat(255);e evitando o .join?
Dom Hastings
1
@DomHastings: as strings JS são imutáveis, então você teria que fazer .split('')isso em uma estrutura de dados mutável, mas nesse ponto Array(255).fill(' ')é mais curto. Na minha versão, a maioria das minhas economias vem de (a) usando a regra "você pode atribuir uma função ou programa" a ser excluída eval(prompt())em troca c=> e (b) usando o Array.prototype.slicemétodo interno com um parâmetro rest para reduzir um pouco a parte lógica .
CR Drost
1
@ChrisDrost ah, é claro ... eu esqueço que é apenas um acessador! A vergonha [].map.call(s[0],também não salva ...
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()

Experimente online

Mego
fonte
1
Você deve poder fazer 'z'[2::5](backticks em vez de apóstrofes) em vez de ''.join(z)salvar um byte, e passar z=[' ']*256para os parâmetros deve salvar outro. Além disso, acho que você pode mudar returnpara print.
Kade
Eu acho que você pode salvar caracteres escrevendo um programa com p=input()(Python 2) em vez de uma função, o que evita o recuo. Além disso, b+len(a)+1pode serb-~len(a)
xnor
1
Na verdade, um programa apenas permite que você faça 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 muito especial, utilizando as variáveis $`e $'que são 'antes da partida' e 'depois da partida', respectivamente, em vez de dividir a sequência. Eu usei um $}para a variável string como originalmente estava me salvando um byte, mas não existe mais!

Exemplo de execução:

$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

Outra versão que imprime cada linha (por menos um byte!). (Sim, fiz isso porque não li a pergunta corretamente ...)

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

Exemplo de execução:

$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
fonte
2

PHP - 84 bytes

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

Usa códigos de escape ANSI para posicionar o cursor ( \x1b[XGapresentando o caractere Escape e X sendo a coordenada baseada em 1), seguida pela *sequência de caracteres de entrada da linha. Aceita entrada na linha de comando do formulário:

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

Aceita entradas com várias palavras se estiverem entre aspas, pois são argumentos de linha de comando.

Niet, o Escuro Absol
fonte
1

C ++ 11, 95 bytes

Por que não?

Como função, receba entrada como um map<int, string>nome vcontendo a posição e a sequência.

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;
}

Verifique aqui em execução

wendelbsilva
fonte