Formate uma lista de palavras

16

Seu desafio é formatar uma lista de palavras em várias linhas que não tenham mais que um determinado número de caracteres, para que cada linha contenha o maior número possível de palavras e que nenhuma seja desnecessariamente cortada.

Entrada

A entrada será uma lista de palavras separadas por espaço e, em seguida, um número que seja pelo menos 4.

Resultado

A saída deve ser as palavras de entrada agrupadas em linhas, para que nenhuma das linhas contenha mais caracteres que o número de entrada. As palavras devem ser exibidas na ordem em que foram inseridas. As palavras devem ser separadas por vírgula e depois por um espaço, exceto no final de cada linha, onde o espaço não é necessário. Se uma palavra for muito longa para caber em uma linha, ela deve ser cortada o menos possível enquanto segue as outras regras e "..." deve ser adicionado ao final.

Casos de teste

Input:
foo bar baz qux 12

Output:
foo, bar,
baz, qux


Input:
foo bar baz qux 5

Output:
foo,
bar,
baz,
qux


Input:
strength dexterity constitution intelligence wisdom charisma 10

Output:
strength,
dexterity,
consti...,
intell...,
wisdom,
charisma


Input:
quas wex exort 4

Output:
...,
wex,
e...
KSFT
fonte
Relacionados
Peter Taylor

Respostas:

10

Ilegível , 2559 bytes

Esse desafio é assustadoramente adequado para ilegível.

A primeira versão disso era 3379 bytes, apenas para lhe dar uma idéia do quanto eu joguei isso.

O programa aceita a entrada exatamente como descrito no desafio: uma lista de palavras separadas por espaço (que também podem conter dígitos e sinais de pontuação), seguida por um espaço e um número inteiro que é pelo menos 4 (números mais baixos geram loops infinitos) .

'"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "'" "" ""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" ""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "'" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" '""' "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""'""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" "" ""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" ""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "'" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "'" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" ""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" '' '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ '' '"'" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "'"' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "

Explicação

Vou mostrar como o programa processa a entrada thyme horseradish peppermint 10. A saída esperada é thyme,\nhorser...,\npeppermint.

Primeiro, começamos na célula 7 e lemos toda a entrada, mas subtraímos 32 de cada caractere para que os espaços se tornem zeros.

Por razões óbvias, isso deixa o ponteiro em execução (chamado p aqui, armazenado na célula # 0) no final. Usamos um loop while para encontrar a última lacuna, que é o começo do número que define a largura da saída (célula nº 36 neste exemplo).

Agora queremos decodificar o número (ou seja, converter de decimal). O resultado final será nas células t e r . Contamos com o fato de que eles começam do zero.

Para cada dígito no número, faça o seguinte:

  • Defina t para -15.
  • Em um loop while, decrement r (que contém o resultado até agora) para 1 (porque precisamos exatamente r iterações, mas desde que o decréscimo acontece antes de ser verificado que a condição de loop while, diminuindo a 0 daria um menor número de iterações) e para cada iteração, adicione 10 a t . Agora t contém 10 vezes o resultado anterior menos 15.
  • Novamente em um loop while, diminua * p para 0 e, para cada iteração, adicione 1 a t . Depois que t contém o resultado intermediário correto até o momento: os caracteres '0'com '9'códigos ASCII 48–57; portanto, após a subtração anterior de 32, eles são 16–25; portanto, adicionamos 15–24 a t , o que cancela com −15. nós configuramos para mais cedo. Também é importante que isso zere as células que costumavam conter os caracteres de dígito para que o código subseqüente possa reconhecer o final da lista de palavras.
  • Defina r para o novo resultado intermediário para que a próxima iteração o encontre em r . (Observe que não precisamos ler de t novamente, podemos apenas usar o último valor do loop while anterior, porque sabemos que * p não pode ser zero, portanto, ele foi executado pelo menos uma vez.)

Finalmente, usamos outro loop while simples (diminuindo t como o contador) para converter o número que acabamos de calcular em unário. Armazenamos uma sequência de 1s indo para a esquerda a partir da célula # 0. Isso se baseia no fato de que a célula nº 1, nosso ponteiro em execução para este ( q ), começa em 0. Temos um 1s a menos porque os loops em Ilegível são assim:

Depois disso, não precisamos mais do valor em r , então reutilizamos essa célula para outra coisa. Nós redefinir a ponteiros p e q e inicializar algumas células com códigos ASCII de caracteres que precisamos mais tarde. Eu também rotulei c e s, que usaremos mais tarde, e confiaremos no fato de que s começa em zero:

Ei, espera um pouco. Por que a célula # 0 está vermelha? ... Bem, isso é para destacar um truque sorrateiro. Lembre-se de que produzimos um 1 a menos? O truque é que usamos a célula # 0 como uma "extensão" para corrigir isso. Isso funciona porque sabemos que p nunca será 0. Dessa forma, o bloco vermelho agora tem 10 células de largura, exatamente o número que queremos. Ele também salva 9 caracteres para poder inicializar q para 1 em vez de 0.

Agora, entramos no loop while, que percorre as palavras e gera todas elas.

Etapa 1: descubra se a próxima palavra se encaixará na linha atual. Para fazer isso, basta mover p para a direita eq para a esquerda com um loop while até que p atinja a próxima lacuna:

Agora que p está à direita da palavra, podemos verificar se esta é a última palavra da lista, verificando se * (p + 1) é zero. Também armazenamos esse valor (que em nosso exemplo é 72 porque é o "h" de "rábano silvestre" menos 32) em c porque precisamos dele novamente mais tarde. Nesse caso, não é zero; portanto, precisamos gerar uma vírgula junto com a palavra, para que a palavra tenha um caractere a mais. Considere isso diminuindo q mais uma vez. Por fim, use outro loop while para retornar p ao início da palavra.

Agora sabemos que a palavra se encaixará na linha atual porque q está apontando para um valor diferente de zero, então tudo o que precisamos fazer é:

  • Mover p a frente através da palavra de novo, imprimindo cada personagem (mais de 32, porque todos os códigos ASCII são desativados por 32).
  • Se c for diferente de zero, imprima uma vírgula (usando o valor na célula nº 5).
  • Defina s como um valor diferente de zero para indicar para a próxima iteração que não estamos mais no início de uma linha e, portanto, precisamos gerar um caractere de espaço antes da próxima palavra. (Reutilizamos o valor de retorno da declaração de impressão acima para isso, que é 44 para a vírgula.)

Saída até agora: thyme,

Em seguida, a próxima iteração do grande loop é iniciada. Como antes, verificamos se a próxima palavra se encaixa no restante da linha, diminuindo q à medida que passamos pela palavra da esquerda para a direita. Observe que q ainda é –5 da iteração anterior, mantendo o controle de quantos caracteres já imprimimos na linha atual. Depois de contar os caracteres em "rábano", mais um para a vírgula, mais um porque s é diferente de zero, indicando que também precisamos gerar um espaço, q terá ultrapassado o final do bloco de 1s:

Agora q aponta para uma célula zero, o que significa que o "rábano silvestre" não se ajustará à linha atual. O que fazemos agora depende se s é diferente de zero. No nosso caso, é o que significa que precisamos avançar para a próxima linha. Tudo o que precisamos fazer é:

  • Imprimir uma nova linha (usando a célula nº 3)
  • Defina q de volta para 1
  • Defina s como 0

Saída até agora: thyme,\n

Para a próxima iteração, p está no mesmo lugar que antes, portanto, veremos a mesma palavra novamente. Como antes, contamos os caracteres em "raiz-forte", definimos c como 80 novamente quando notamos que há outra palavra após esta, diminui q para a vírgula e retrocede p de volta ao início da palavra:

Como na iteração anterior, descobrimos que "raiz forte" ainda não se encaixa porque q acaba em uma célula que é zero. No entanto, desta vez s é zero, o que significa que fazemos algo diferente da última vez. Precisamos produzir parte da palavra, três pontos e uma vírgula. Nossa largura é 10, portanto, precisamos gerar 6 caracteres da palavra. Vamos ver onde terminamos se:

  • Encontre o início do bloco vermelho de 1s. Podemos fazer isso indo para a direita, porque sabemos que q deve ser deixado dela.
  • Incremente q mais uma vez se também precisarmos gerar uma vírgula ( c ≠ 0).

A fita agora fica assim:

Eu marquei um espaço de 6 células aqui. Como você pode ver, precisamos gerar caracteres até q = -1. Isso é muito eficiente em termos de código para verificar (basicamente while ((++q)+1) { ... }). Então:

  • Imprima esses caracteres (mais 32, porque todos os códigos ASCII estão desativados em 32) até q atingir -1. p estará então na célula 19, no meio da palavra "rábano".
  • Imprima três pontos. Como o comando print retorna seu próprio argumento, podemos aninhar com eficiência o código (essencialmente print(print(print('.')))). Pegamos o valor ASCII da célula nº 5 e adicionamos 2 para obter o código ASCII do ponto.
  • Mova p para o final da palavra. Como sabemos que ainda não podemos chegar ao final da palavra (porque a palavra era muito longa e tivemos que remover pelo menos três caracteres para ajustar os pontos), esse loop definitivamente tem pelo menos uma iteração, portanto seu código é mais curto para que o corpo do loop while calcule o valor ASCII do ponto e depois passe o valor de retorno do loop while para as funções de impressão.
  • Imprima uma vírgula se c for diferente de zero.

Depois de tudo isso, também imprimimos uma nova linha (usando a célula nº 3) e configuramos q de volta para 1. Também podemos definir s como 0, mesmo que já seja 0, o que torna o mesmo que fizemos anteriormente quando envolvemos o arquivo próxima linha (quando s é diferente de zero), para evitar repetir o código, fazemos isso após o condicional que verifica s .

Saída até agora: thyme,\nhorser...,\n

Há apenas uma iteração restante. Desta vez, depois de contar as letras da palavra, obtemos o seguinte:

Desta vez, como não há nada após p , definimos c como 0 para indicar “sem vírgula” e, portanto, não diminuímos q mais uma vez. Como q agora aponta para uma célula diferente de zero, sabemos que a palavra se ajustará; portanto, o mesmo código é executado como na primeira iteração, exceto que, desta vez, c é zero e, portanto, simplesmente não imprime a vírgula.

Resultado: thyme,\nhorser...,\npeppermint

Nesta explicação passo a passo, não incluí um caso em que o código realmente imprimiria um espaço, mas acho que deveria estar bem claro agora. Se o código achar que a palavra se encaixa ( * q ≠ 0) e s é diferente de zero, ele simplesmente produzirá um espaço antes da palavra.

Timwi
fonte
3

JavaScript (ES6), 171

Como uma função anônima retornando a saída como uma matriz

(como isso geralmente é permitido, a menos que seja explicitamente proibido: meta meta )

s=>(s=s.split` `,n=s.pop()-1,t='',o=[],s.map((w,i)=>(w=w[n+=!s[i+1]]?w.slice(0,n-3)+'...':w,(t+w)[n-2]&&(t&&o.push(t.slice(1)),t=''),t+=` ${w},`)),o.push(t.slice(1,-1)),o)

f=s=>(s=s.split` `,n=s.pop()-1,t='',o=[],s.map((w,i)=>(w=w[n+=!s[i+1]]?w.slice(0,n-3)+'...':w,(t+w)[n-2]&&(t&&o.push(t.slice(1)),t=''),t+=` ${w},`)),o.push(t.slice(1,-1)),o)

// Less golfed
U=s=>(
  s=s.split` `,
  n=s.pop()-1,
  t='', // current line
  o=[], // output
  s.map( (w,i)=>(
    w=w[
      n+=!s[i+1] // space for 1 more char on the last line
    ]?w.slice(0,n-3)+'...':w, // change w if it is too long
    (t+w)[n-2]&& ( // if current line + w is too long, ouput t and reset current line
      t&&o.push(t.slice(1)),t=''
    ),
    t+=` ${w},`
  )),
  o.push(t.slice(1,-1)), // remove tailing comma on last line
  o
)

console.log=x=>O.textContent+=x+'\n\n';
  
console.log(f("foo bar baz qux 12").join`\n`)
console.log(f("foo bar baz qux 5").join`\n`)
console.log(f("strength dexterity constitution intelligence wisdom charisma 10").join`\n`)
console.log(f("quas wex exort 4").join`\n`)
<pre id=O></pre>

edc65
fonte
1

Python 2, 206 bytes

i=input().split()
l=int(i.pop())
i=[[w[:l-4]+'...',w][len(w)<l]+','for w in i][:-1]+[[w,w[:l-3]+'...'][len(w)>l]]
r=[i.pop(0)]
for w in i:
 if len(r[-1])+len(w)<l:r[-1]+=' '+w
 else:r+=[w]
print'\n'.join(r)
TFeld
fonte