Formater une liste de mots

16

Votre défi est de formater une liste de mots sur plusieurs lignes qui ne dépassent pas un nombre donné de caractères, afin que chaque ligne contienne autant de mots que possible et qu'aucun mot ne soit inutilement coupé.

Contribution

L'entrée sera une liste de mots séparés par des espaces, puis un nombre d'au moins 4.

Production

La sortie doit être les mots d'entrée regroupés en lignes de sorte qu'aucune des lignes ne contienne plus de caractères que le numéro d'entrée. Les mots doivent être sortis dans l'ordre où ils ont été saisis. Les mots doivent être séparés par une virgule puis un espace, sauf à la fin de chaque ligne, où l'espace n'est pas nécessaire. Si un mot est trop long pour tenir sur une ligne, il doit être coupé le moins possible en suivant les autres règles et "..." doit être ajouté à la fin.

Cas de test

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
la source
En relation
Peter Taylor

Réponses:

10

Illisible , 2559 octets

Ce défi est étrangement adapté pour Illisible.

La première version était de 3379 octets, juste pour vous donner une idée de combien j'ai joué au golf.

Le programme accepte l'entrée exactement comme décrit dans le défi: une liste de mots séparés par des espaces (qui peuvent également contenir des chiffres et des signes de ponctuation), suivi d'un espace et d'un entier d'au moins 4 (les nombres inférieurs génèrent des boucles infinies) .

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

Explication

Je vais vous expliquer comment le programme traite les entrées thyme horseradish peppermint 10. La sortie attendue est thyme,\nhorser...,\npeppermint.

D'abord, nous commençons à la cellule # 7 et lisons l'intégralité de l'entrée, mais soustrayons 32 de chaque caractère afin que les espaces deviennent des zéros.

Pour des raisons évidentes, cela laisse le pointeur en cours d'exécution (nommé p ici, stocké dans la cellule # 0) à la fin. Nous utilisons une boucle while pour trouver le dernier intervalle, qui est le début du nombre qui définit la largeur de la sortie (cellule # 36 dans cet exemple).

Nous voulons maintenant décoder le nombre (c'est-à-dire convertir de décimal). Le résultat final sera dans les cellules t et r . Nous comptons sur le fait qu’ils partent de zéro.

Pour chaque chiffre du numéro, procédez comme suit:

  • Réglez t sur −15.
  • Dans une boucle while, décrémentez r (qui contient le résultat jusqu'à présent) à −1 (car nous avons besoin d'exactement r itérations, mais puisque la décrémentation se produit avant qu'elle ne soit vérifiée comme condition de la boucle while, la décrémentation à 0 donnerait une itération de moins) et pour chaque itération, ajoutez 10 à t . Maintenant, t contient 10 fois le résultat précédent moins 15.
  • Toujours dans une boucle while, décrémentez * p à 0 et pour chaque itération, ajoutez 1 à t . Après cela, t contient le résultat intermédiaire correct jusqu'à présent: les caractères '0'pour '9'avoir les codes ASCII 48–57, donc après la soustraction précédente de 32, ils sont 16–25, donc nous ajoutons en fait 15–24 à t , ce qui annule avec le −15 nous l'avons réglé plus tôt. Il est également important que cela remette à zéro les cellules qui contenaient les caractères numériques afin que le code suivant puisse reconnaître la fin de la liste de mots.
  • Définissez r sur le nouveau résultat intermédiaire de sorte que l'itération suivante le trouve dans r . (Notez que nous n'avons pas besoin de relire à partir de t , nous pouvons simplement utiliser la dernière valeur de la boucle while précédente car nous savons que * p ne peut pas être nul, il a donc été exécuté au moins une fois.)

Enfin, nous utilisons une autre boucle while simple (décrémentant t comme compteur) pour convertir le nombre que nous venons de calculer en unaire. Nous stockons une chaîne de 1 allant vers la gauche à partir de la cellule # 0. Cela repose sur le fait que la cellule # 1, notre pointeur en cours d'exécution pour ce ( q ), commence à 0. Nous obtenons un 1 de moins car les boucles en illisibles sont comme ça:

Après cela, nous n'avons plus besoin de la valeur de r , nous réutilisons donc cette cellule pour autre chose. Nous réinitialisons les pointeurs p et q et initialisons certaines cellules avec les codes ASCII des caractères dont nous avons besoin plus tard. J'ai également étiqueté c et s que nous utiliserons plus tard, et nous nous appuierons sur le fait que s commence à zéro:

Hé, attends une minute. Pourquoi la cellule # 0 est-elle colorée en rouge? ... Eh bien, c'est pour mettre en évidence une astuce sournoise. Rappelez-vous que nous en sortons un 1 trop peu? L'astuce est que nous utilisons la cellule # 0 comme une «extension» pour corriger cela. Cela fonctionne parce que nous savons que p ne sera jamais égal à 0. De cette façon, le bloc rouge fait maintenant 10 cellules de large, exactement le nombre que nous voulons. Il enregistre également 9 caractères pour pouvoir initialiser q à 1 au lieu de 0.

Maintenant, nous entrons dans la boucle while qui passe par les mots et les sort tous.

Étape 1: Découvrez si le mot suivant rentrera dans la ligne actuelle. Pour ce faire, il suffit de déplacer p vers la droite et q vers la gauche avec une boucle while jusqu'à ce que p atteigne l'écart suivant:

Maintenant que p est à droite du mot, nous pouvons vérifier s'il s'agit du dernier mot de la liste en vérifiant si * (p + 1) est zéro. Nous stockons également cette valeur (qui dans notre exemple est 72 car c'est le "h" de "raifort" moins 32) dans c car nous en aurons besoin plus tard. Dans ce cas, ce n'est pas zéro, donc nous devrons sortir une virgule avec le mot, donc le mot est un caractère plus long. Tenez-en compte en décrémentant q une fois de plus. Enfin, utilisez une autre boucle while pour ramener p au début du mot.

Nous savons maintenant que le mot rentrera dans la ligne courante parce que q pointe sur une valeur non nulle, donc tout ce que nous avons à faire est:

  • Déplacez à nouveau p vers l'avant dans le mot, en imprimant chaque caractère (plus 32, car tous les codes ASCII sont désactivés par 32).
  • Si c est différent de zéro, imprimez une virgule (en utilisant la valeur de la cellule # 5).
  • Définissez s sur une valeur non nulle pour indiquer à l'itération suivante que nous ne sommes plus au début d'une ligne et que nous devons donc sortir un caractère espace avant le mot suivant. (Nous réutilisons pour cela la valeur de retour de l'instruction print ci-dessus, qui est 44 pour la virgule.)

Sortie jusqu'à présent: thyme,

Ensuite, l'itération suivante de la grande boucle commence. Comme précédemment, nous vérifions si le mot suivant s'inscrit dans le reste de la ligne en décrémentant q lorsque nous parcourons le mot de gauche à droite. Notez que q est toujours −5 par rapport à l'itération précédente, gardant une trace du nombre de caractères que nous avons déjà imprimés dans la ligne actuelle. Après avoir compté les caractères en "raifort", plus un pour la virgule, plus un parce que s est différent de zéro indiquant que nous devons également afficher un espace, q aura dépassé la fin du bloc de 1:

Maintenant, q pointe vers une cellule zéro, ce qui signifie que le "raifort" ne rentrera pas dans la ligne courante. Ce que nous faisons maintenant dépend de si s est non nul. Dans notre cas, c'est le cas, ce qui signifie que nous devons passer à la ligne suivante. Il nous suffit pour cela:

  • Imprimer une nouvelle ligne (en utilisant la cellule # 3)
  • Réglez q sur 1
  • Mettre s à 0

Sortie jusqu'à présent: thyme,\n

Pour la prochaine itération, p est au même endroit qu'auparavant, nous allons donc revoir le même mot. Comme précédemment, nous comptons les caractères dans "raifort", remettons c à 80 lorsque nous remarquons qu'il y a un autre mot après celui-ci, décrémentons q pour la virgule et rembobinons p au début du mot:

Comme dans l'itération précédente, nous constatons que le «raifort» ne correspond toujours pas parce que q se retrouve sur une cellule qui est nulle. Cependant, cette fois -ci est est nul, ce qui signifie que nous faisons quelque chose de différent que la dernière fois. Nous devons sortir une partie du mot, trois points et une virgule. Notre largeur est de 10, nous devons donc afficher 6 caractères du mot. Voyons où nous nous retrouvons si nous:

  • Trouvez le début du bloc rouge de 1. Nous pouvons le faire en allant à droite car nous savons que q doit en rester.
  • Incrémentez q une fois de plus si nous devons également sortir une virgule ( c ≠ 0).

La bande ressemble maintenant à ceci:

J'ai marqué une plage de 6 cellules ici. Comme vous pouvez le voir, nous devons sortir des caractères jusqu'à q = −1. C'est très efficace pour vérifier le code (en gros, while ((++q)+1) { ... }). Donc:

  • Imprimez ces caractères (plus 32, car tous les codes ASCII sont désactivés par 32) jusqu'à ce que q atteigne -1. p sera alors à la cellule 19, au milieu du mot «raifort».
  • Imprimez trois points. Étant donné que la commande print renvoie son propre argument, nous pouvons l'imbriquer de manière efficace (essentiellement print(print(print('.')))). Nous prenons la valeur ASCII de la cellule # 5 et y ajoutons 2 pour obtenir le code ASCII du point.
  • Déplacez p à la fin du mot. Puisque nous savons que nous ne pouvons pas avoir déjà atteint la fin du mot (parce que le mot était trop long et que nous avons dû en supprimer au moins 3 caractères pour correspondre aux points), cette boucle a définitivement au moins une itération, donc le code est plus court pour que le corps de la boucle while calcule la valeur ASCII du point, puis transmette la valeur de retour de la boucle while aux fonctions d'impression.
  • Imprime une virgule si c est différent de zéro.

Après tout cela, nous imprimons également une nouvelle ligne (à l'aide de la cellule # 3) et redéfinissons q à 1. Nous pouvons également définir s à 0 même s'il est déjà 0, ce qui en fait la même chose que nous l'avons fait précédemment lorsque nous avons encapsulé dans le ligne suivante (lorsque s était non nul), donc pour éviter de répéter le code, nous le faisons après le conditionnel qui vérifie s .

Sortie jusqu'à présent: thyme,\nhorser...,\n

Il ne reste qu'une seule itération. Cette fois, après avoir compté les lettres du mot, nous obtenons ceci:

Cette fois, il n'y a rien après p , donc nous mettons c à 0 pour indiquer «pas de virgule», et en conséquence nous ne décrémentons pas q une nouvelle fois. Puisque q pointe maintenant vers une cellule non nulle, nous savons que le mot conviendra, donc le même code est exécuté que lors de la première itération, sauf que cette fois c vaut zéro, donc il n'imprimera tout simplement pas la virgule.

Production: thyme,\nhorser...,\npeppermint

Dans cette procédure pas à pas, je n'ai pas inclus de cas où le code imprimerait réellement un espace, mais je pense que cela devrait être assez clair maintenant. Si le code trouve que le mot convient ( * q ≠ 0) et que s est différent de zéro, il affichera simplement un espace avant le mot.

Timwi
la source
3

JavaScript (ES6), 171

En tant que fonction anonyme renvoyant la sortie sous forme de tableau

(car cela est généralement autorisé sauf si explicitement interdit: 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
la source
1

Python 2, 206 octets

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
la source