Conseils pour jouer au golf à la rétine

10

Quels conseils généraux avez-vous pour jouer au golf à Retina ? Je cherche des idées qui peuvent être appliquées aux problèmes de golf de code en général qui sont au moins quelque peu spécifiques à Retina (par exemple, "supprimer les commentaires" n'est pas une réponse). Veuillez poster un pourboire par réponse.

Pour référence, le compilateur en ligne est ici .

@ Sp3000 a souligné qu'il existe également des conseils pour Regex Golf . Les réponses ici devraient se concentrer spécifiquement sur les fonctionnalités de la rétine et non sur les conseils généraux de golf regex.

Traumatisme numérique
la source
2
Connexes: Conseils pour le golf regex
Sp3000
Hmmm, je n'ai pas posté ceci parce que Retina est encore en développement et j'avais peur que la plupart des réponses finissent par être des conseils de golf regex simples, pas très spécifiques à Retina. Mais nous pourrions aussi bien essayer, je suppose ... :)
Martin Ender
@ MartinBüttner Vous et quelques autres m'avez donné beaucoup de bons conseils et astuces depuis que j'ai commencé à regarder Retina, donc je pense qu'il est probablement temps pour cela. J'ai ajouté une clarification que les conseils généraux sur les expressions rationnelles devraient aller à la question liée.
Digital Trauma
1
@ MartinBüttner Voici le meilleur endroit où demander - je me demande depuis un certain temps - par curiosité quelle est l'inspiration pour le nom "Retina"? Je suppose que la partie "Re" est pour l'expression régulière, mais qu'en est-il de la "tina"?
Digital Trauma
3
@DigitalTrauma J'essayais de trouver un beau mot qui fonctionnerait comme un acronyme, mais a échoué. Le mot «rétine» était assez proche de certaines tentatives, et j'ai aimé le mot. Je n'ai jamais réussi à le reconvertir en acronyme et j'ai depuis abandonné cela. Donc oui, le "re" est en quelque sorte pour les "expressions régulières" et peut-être le "n" pour ".NET", mais finalement c'est juste un mot qui sonnait bien.
Martin Ender

Réponses:

3

Combinez les boucles si possible

Dans les calculs non triviaux, vous vous retrouverez souvent à utiliser plusieurs boucles pour traiter les données:

+`stage1
+`stage2
+`stage3

Donc, cela fonctionne stage1jusqu'à ce que la sortie converge, puis stage2jusqu'à ce que la sortie converge, puis stage3jusqu'à ce que la sortie converge.

Cependant, cela vaut toujours la peine d'examiner les étapes en détail. Parfois, il est possible d'exécuter la boucle de manière entrelacée à la stage1, stage2, stage3, stage1, stage2, stage3, ...place (cela dépend beaucoup de ce que les étapes font réellement, mais parfois elles font des changements complètement orthogonaux ou fonctionnent bien comme un pipeline). Dans ce cas, vous pouvez enregistrer des octets en les enveloppant dans une seule boucle:

{`stage1
stage2
}`stage3

Si stage1c'est la première étape ou stage3la dernière étape du programme, vous pouvez même omettre également l'une de ces parenthèses (ce qui signifie que cela peut déjà enregistrer des octets pour une boucle de deux étapes).

Une utilisation récente de cette technique peut être vue dans cette réponse .

Martin Ender
la source
2

Fractionnement de chaînes en morceaux de longueur égale n

Comme dans la plupart des langues "normales" TMTOWTDI (il y a plus d'une façon de le faire). Je suppose ici que l'entrée ne contient pas de sauts de ligne, et que "fractionner" signifie la diviser en lignes. Mais il y a deux objectifs très différents: si la longueur de la chaîne n'est pas un multiple de la longueur du morceau, voulez-vous conserver le morceau de fin incomplet ou voulez-vous le supprimer?

Garder un morceau de fin incomplet

En général, il existe trois façons de procéder au fractionnement de la rétine. Je présente les trois approches ici, car elles pourraient faire une plus grande différence lorsque vous essayez de les adapter à un problème connexe. Vous pouvez utiliser un remplacement et ajouter un saut de ligne à chaque correspondance:

.{n}
$&¶

C'est 8 octets (ou un peu moins si n = 2ou n = 3parce qu'alors vous pouvez utiliser ..ou ...respectivement). Cependant, cela a un problème: il ajoute un saut de ligne supplémentaire si la longueur de la chaîne est un multiple de la longueur du bloc.

Vous pouvez également utiliser une étape fractionnée et utiliser le fait que les captures sont conservées dans la division:

S_`(.{n})

L' _option supprime les lignes vides qui résulteraient autrement de la couverture de la chaîne entière avec des correspondances. C'est 9 octets, mais cela n'ajoute pas de saut de ligne de fin. Pour n = 3c'est 8 octets et pour n = 2c'est 7 octets. Notez que vous pouvez enregistrer un octet dans l'ensemble si les lignes vides n'ont pas d'importance (par exemple parce que vous ne traiterez que les lignes non vides et vous débarrasserez des sauts de ligne de toute façon plus tard): alors vous pouvez supprimer le _.

La troisième option consiste à utiliser une correspondance. Avec l' !option, nous pouvons imprimer tous les matchs. Cependant, pour inclure le fragment de fin, nous devons autoriser une longueur de correspondance variable:

M!`.{1,n}

Cela représente également 9 octets et n'inclura pas non plus de saut de ligne. Cela devient également 8 octets pour n = 3en faisant ..?.?. Notez cependant qu'il se réduit à 6 octets n = 2car maintenant nous n'en avons besoin que ..?. Notez également que le Mpeut être supprimé s'il s'agit de la dernière étape de votre programme, en économisant un octet dans tous les cas.

Jeter un fragment de fin incomplet

Cela devient vraiment long si vous essayez de le faire avec un remplacement, car vous devez remplacer le morceau de fin par rien (s'il existe) et également par un fractionnement. Nous pouvons donc les ignorer en toute sécurité. Fait intéressant, pour l'approche par match, c'est l'inverse: elle raccourcit:

M!`.{n}

C'est 7 octets, ou moins pour n = 2, n = 3. Encore une fois, notez que vous pouvez omettre le Msi c'est la dernière étape du code.

Si vous voulez un saut de ligne de fin ici, vous pouvez l'obtenir en l'ajoutant |$à l'expression régulière.

Bonus: morceaux qui se chevauchent

N'oubliez pas que Ml' &option a pour résultat de renvoyer des correspondances qui se chevauchent (ce qui n'est normalement pas possible avec regex). Cela vous permet d'obtenir tous les morceaux (sous-chaînes) qui se chevauchent d'une chaîne d'une longueur donnée:

M!&`.{n}
Martin Ender
la source
Est-il possible de diviser une chaîne exactement en deux avec une longueur variable? Alors 123456devient 123\n456et 1234567890devient 12345\n67890?
Kevin Cruijssen
1
@KevinCruijssen Je ne pense pas avoir ajouté de fonctionnalité spécifique pour cela. Vous devrez probablement utiliser des groupes d'équilibrage: tio.run/##K0otycxLNPyvquGe8D/YIEHD3sZWQ09TW1PD3hbI1jW0A3JUNP//… Si cela ne vous dérange pas un saut de ligne arrière, vous pouvez omettre le ?=.
Martin Ender
J'ai pu relever le défi là où je pensais en avoir besoin différemment, mais les groupes d'équilibrage sont en effet très utiles! Je savais que cela devait être quelque chose dans ce sens, mais mes compétences en regex / rétine ne sont pas assez bonnes. Merci de répondre! :)
Kevin Cruijssen