Dar formato a una lista de palabras

16

Su desafío es formatear una lista de palabras en varias líneas que no tengan más de un número dado de caracteres, de modo que cada línea contenga la mayor cantidad de palabras posible y ninguna palabra se corte innecesariamente.

Entrada

La entrada será una lista de palabras separadas por espacios y luego un número que sea al menos 4.

Salida

La salida debe ser las palabras de entrada agrupadas en líneas para que ninguna de las líneas contenga más caracteres que el número de entrada. Las palabras deben salir en el orden en que fueron ingresadas. Las palabras deben estar separadas por una coma y luego un espacio, excepto al final de cada línea, donde el espacio no es necesario. Si una palabra es demasiado larga para caber en una línea, se debe cortar lo menos posible mientras se siguen las otras reglas, y se debe agregar "..." al final.

Casos de prueba

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
fuente
Relacionado
Peter Taylor

Respuestas:

10

Ilegible , 2559 bytes

Este desafío es inquietantemente apto para ilegible.

La primera versión de esto tenía 3379 bytes, solo para darte una idea de cuánto jugué al golf.

El programa acepta la entrada exactamente como se describe en el desafío: una lista de palabras separadas por espacios (que también pueden contener dígitos y signos de puntuación), seguidas de un espacio y un número entero que es al menos 4 (los números más bajos generan bucles infinitos) .

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

Explicación

Voy a guiarlo a través de cómo el programa procesa la entrada thyme horseradish peppermint 10. La salida esperada es thyme,\nhorser...,\npeppermint.

Primero comenzamos en la celda # 7 y leemos la entrada completa, pero restamos 32 de cada carácter para que los espacios se conviertan en ceros.

Por razones obvias, esto deja el puntero en ejecución (llamado p aquí, almacenado en la celda # 0) al final. Usamos un bucle while para encontrar el último espacio, que es el comienzo del número que define el ancho de la salida (celda # 36 en este ejemplo).

Ahora queremos decodificar el número (es decir, convertir de decimal). El resultado final estará en ambas celdas t y r . Confiamos en el hecho de que comienzan en cero.

Para cada dígito en el número, haga lo siguiente:

  • Establezca t en −15.
  • En un ciclo while, disminuir r (que contiene el resultado hasta ahora) a -1 (porque necesitamos exactamente r iteraciones, pero dado que la disminución ocurre antes de que se verifique como la condición del ciclo while, disminuir a 0 daría una iteraciones menos) y para cada iteración, agregue 10 a t . Ahora t contiene 10 veces el resultado anterior menos 15.
  • Nuevamente en un ciclo while, disminuya * p a 0 y para cada iteración, agregue 1 a t . Después de esto t contiene el resultado intermedio correcta hasta el momento: los personajes '0'que '9'tienen códigos ASCII 48-57, así que después de la resta anterior de 32 que son 16-25, así que en realidad añadimos a 15-24 t , que cancela con el -15 Lo configuramos para antes. También es importante que esto ponga a cero las celdas que solían contener los caracteres de dígitos para que el código posterior pueda reconocer el final de la lista de palabras.
  • Establezca r en el nuevo resultado intermedio para que la próxima iteración lo encuentre en r . (Tenga en cuenta que no necesitamos leer de nuevo t , solo podemos usar el último valor del ciclo while anterior porque sabemos que * p no puede ser cero, por lo que se ha ejecutado al menos una vez).

Finalmente, usamos otro ciclo while simple (decrementando t como el contador) para convertir el número que acabamos de calcular en unario. Almacenamos una cadena de 1s hacia la izquierda desde la celda # 0. Esto se basa en el hecho de que la celda n. ° 1, nuestro puntero en ejecución para esto ( q ), comienza en 0. Obtenemos un 1 menos porque los bucles en Unreadable son así:

Después de esto, ya no necesitamos el valor en r , por lo que reutilizamos esa celda para otra cosa. Restablecemos los punteros p y q e inicializamos algunas celdas con códigos ASCII de caracteres que necesitamos más adelante. También he etiquetado c y s que usaremos más tarde, y confiaremos en el hecho de que s comienza en cero:

Oye, espera un minuto. ¿Por qué la celda # 0 es de color rojo? ... Bueno, esto es para resaltar un truco furtivo. ¿Recuerdas que sacamos uno 1 muy pocos? El truco es que usamos la celda # 0 como una "extensión" para corregir eso. Esto funciona porque sabemos que p nunca será 0. De esta manera, el bloque rojo ahora tiene 10 celdas de ancho, exactamente el número que queremos. También guarda 9 caracteres para poder inicializar q a 1 en lugar de 0.

Ahora ingresamos al ciclo while que pasa por las palabras y las genera todas.

Paso 1: averigua si la siguiente palabra se ajustará a la línea actual. Hacemos esto simplemente moviendo p hacia la derecha yq hacia la izquierda con un ciclo while hasta que p llegue al siguiente espacio:

Ahora que p está a la derecha de la palabra, podemos verificar si esta es la última palabra en la lista comprobando si * (p + 1) es cero. También almacenamos ese valor (que en nuestro ejemplo es 72 porque es la "h" de "rábano picante" menos 32) en c porque lo necesitaremos nuevamente más tarde. En este caso, no es cero, por lo que tendremos que mostrar una coma junto con la palabra, por lo que la palabra tiene un carácter más largo. Tenga esto en cuenta disminuyendo q una vez más. Finalmente, use otro bucle while para mover p al principio de la palabra.

Ahora sabemos que la palabra se ajustará a la línea actual porque q apunta a un valor distinto de cero, por lo que todo lo que tenemos que hacer es:

  • Mueva p hacia adelante a través de la palabra nuevamente, imprimiendo cada carácter (más 32, porque todos los códigos ASCII están desactivados en 32).
  • Si c no es cero, imprima una coma (usando el valor en la celda # 5).
  • Establezca s en un valor distinto de cero para indicar a la siguiente iteración que ya no estamos al comienzo de una línea y, por lo tanto, necesitamos generar un carácter de espacio antes de la siguiente palabra. (Reutilizamos el valor de retorno de la declaración de impresión anterior para esto, que es 44 para la coma).

Salida hasta ahora: thyme,

Entonces comienza la siguiente iteración del bucle grande. Como antes, verificamos si la siguiente palabra se ajusta al resto de la línea disminuyendo q a medida que avanzamos por la palabra de izquierda a derecha. Tenga en cuenta que q todavía es −5 de la iteración anterior, haciendo un seguimiento de cuántos caracteres ya hemos impreso en la línea actual. Después de contar los caracteres en "rábano picante", más uno para la coma, más uno porque s no es cero, lo que indica que también necesitamos generar un espacio, q habrá superado el final del bloque de 1s:

Ahora q apunta a una celda cero, lo que significa que "rábano picante" no encajará en la línea actual. Lo que hacemos ahora depende de si s no es cero. En nuestro caso lo es, lo que significa que debemos pasar a la siguiente línea. Todo lo que tenemos que hacer para eso es:

  • Imprima una nueva línea (usando la celda # 3)
  • Establezca q de nuevo a 1
  • Establezca s en 0

Salida hasta ahora: thyme,\n

Para la próxima iteración, p está en el mismo lugar que antes, por lo que volveremos a ver la misma palabra. Como antes, contamos los caracteres en “rábano picante”, establecemos c nuevamente en 80 cuando notamos que hay otra palabra después de esta, decrementamos q para la coma y rebobinamos p al principio de la palabra:

Como en la iteración anterior, encontramos que "rábano picante" todavía no encaja porque q termina en una celda que es cero. Sin embargo, esta vez s es cero, lo que significa que hacemos algo diferente que la última vez. Necesitamos mostrar algo de la palabra, tres puntos y una coma. Nuestro ancho es 10, por lo que debemos generar 6 caracteres de la palabra. Veamos dónde terminamos si:

  • Encuentra el comienzo del bloque rojo de 1s. Podemos hacer esto yendo a la derecha porque sabemos que se debe dejar q .
  • Incremente q una vez más si también necesitamos generar una coma ( c ≠ 0).

La cinta ahora se ve así:

He marcado un lapso de 6 celdas aquí. Como puede ver, necesitamos generar caracteres hasta q = −1. Esto es muy eficiente en el código para verificar (básicamente while ((++q)+1) { ... }). Entonces:

  • Imprima esos caracteres (más 32, porque todos los códigos ASCII están desactivados por 32) hasta que q alcance −1. p estará entonces en la celda 19, en el medio de la palabra "rábano picante".
  • Imprime tres puntos. Dado que el comando de impresión devuelve su propio argumento, podemos anidarlo de manera eficiente en código (esencialmente, print(print(print('.')))). Tomamos el valor ASCII de la celda # 5 y le agregamos 2 para obtener el código ASCII del punto.
  • Mueve p al final de la palabra. Como sabemos que no podemos haber llegado al final de la palabra (porque la palabra era demasiado larga y tuvimos que eliminar al menos 3 caracteres para que quepan en los puntos), este bucle definitivamente tiene al menos una iteración, por lo que es más corto en el código que el cuerpo del ciclo while calcule el valor ASCII para el punto y luego pase el valor de retorno del ciclo while a las funciones de impresión.
  • Imprima una coma si c no es cero.

Después de todo esto, también imprimimos una nueva línea (usando la celda n. ° 3) y establecemos q nuevamente en 1. También podemos establecer s en 0 aunque ya sea 0, lo que hace que sea lo mismo que hicimos anteriormente cuando ajustamos siguiente línea (cuando s no era cero), por lo que para evitar repetir el código, lo hacemos después del condicional que verifica s .

Salida hasta ahora: thyme,\nhorser...,\n

Solo queda una iteración. Esta vez, después de contar las letras de la palabra, obtenemos esto:

Esta vez, no hay nada después de p , por lo que establecemos c en 0 para indicar "sin coma" y, en consecuencia, no disminuimos q una vez más. Como q ahora apunta a una celda que no es cero, sabemos que la palabra se ajustará, por lo que se ejecuta el mismo código que en la primera iteración, excepto que esta vez c es cero, por lo que simplemente no imprimirá la coma.

Salida: thyme,\nhorser...,\npeppermint

En este tutorial no incluí un caso en el que el código realmente imprimiera un espacio, pero creo que ahora debería estar bastante claro. Si el código encuentra que la palabra se ajusta ( * q ≠ 0) y s no es cero, simplemente generará un espacio antes de la palabra.

Timwi
fuente
3

JavaScript (ES6), 171

Como una función anónima que devuelve la salida como una matriz

(ya que esto generalmente está permitido a menos que esté explícitamente prohibido: 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
fuente
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
fuente