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...
Réponses:
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 estthyme,\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:
'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.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:
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:
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:
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:print(print(print('.')))
). Nous prenons la valeur ASCII de la cellule # 5 et y ajoutons 2 pour obtenir le code ASCII du point.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.
la source
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 )
la source
Python 2, 206 octets
la source