Le problème
J'ai un tas d'expressions régulières que je dois utiliser dans du code, mais j'utilise un langage de programmation qui ne prend pas en charge l'expression régulière! Heureusement, je sais que la chaîne de test aura une longueur maximale et sera composée uniquement d'ASCII imprimable.
Le défi
Vous devez saisir une expression régulière et un nombre n
, et sortir chaque chaîne composée d'ASCII imprimables (codes ASCII 32 à 126 inclus, à
~
, sans tabulations ni sauts de ligne) d'une longueur inférieure ou égale à n
celle correspondant à cette expression régulière. Vous ne pouvez pas utiliser du tout d'expressions régulières intégrées ou de fonctions de correspondance d'expressions rationnelles dans votre code. Les expressions régulières seront limitées aux suivantes:
- Caractères littéraux (et les échappements, qui forcent un caractère à être littéral,
\.
est donc un littéral.
,\n
est un littéraln
(équivalent à justen
) et\w
est équivalent àw
. Vous n'avez pas besoin de prendre en charge les séquences d'échappement.) .
- caractère générique (n'importe quel caractère)- Classes de caractères,
[abc]
signifie "a ou b ou c" et[d-f]
signifie n'importe quoi de d à f (donc, d ou e ou f). Les seuls caractères qui ont une signification particulière dans une classe de caractères sont[
et]
(qui seront toujours échappés, alors ne vous inquiétez pas),\
(le caractère d'échappement, bien sûr),^
au début de la classe de caractères (qui est une négation ), et-
(qui est une plage). |
- l'opérateur OR, alternance.foo|bar
signifie soitfoo
oubar
, et(ab|cd)e
correspond soitabe
oucde
.*
- faire correspondre le jeton précédent répété zéro ou plusieurs fois, gourmand (il essaie de répéter autant de fois que possible)+
- répété une ou plusieurs fois, gourmand?
- zéro ou une fois- Regroupement avec des parenthèses, aux jetons de groupe pour
|
,*
.+
, ou?
La regex d'entrée sera toujours valide (c'est-à-dire que vous n'avez pas à gérer une entrée comme ?abc
ou (foo
ou toute entrée non valide). Vous pouvez sortir les chaînes dans l'ordre que vous souhaitez, mais chaque chaîne ne doit apparaître qu'une seule fois (ne pas sortir de doublons).
Les cas de test
Entrée: .*
, 1
sortie: (chaîne vide), ,
!
, "
, ..., }
,~
Entrée: w\w+
, 3
sortie: ww
,www
Entrée: [abx-z][^ -}][\\]
, 3
sortie: a~\
, b~\
, x~\
, y~\
,z~\
Entrée: ab*a|c[de]*
, 3
sortie: c
, cd
, ce
, aa
, cde
, ced
, cdd
, cee
,aba
Entrée: (foo)+(bar)?!?
, 6
sortie: foo
, foo!
, foofoo
,foobar
Entrée: (a+|b*c)d
, 4
sortie: ad
, cd
, aad
, bcd
, aaad
,bbcd
Entrée: p+cg
, 4
sortie: pcg
,ppcg
Entrée: a{3}
, 4
sortie:a{3}
Le gagnant
C'est du code-golf , donc le code le plus court en octets gagnera!
la source
|
n'a que très peu de sens. Il ne semble pas gérer les groupes imbriqués oua|b|c
. Quel est le problème avec l'utilisation des explications standard en termes de force de concaténation et d'alternance? (Et vous n'avez aucune excuse pour ne pas utiliser le bac à sable)Réponses:
Haskell
757 705 700 692 679667production:
Explication: celle-ci est une implémentation d'expressions régulières. R est le type regex, avec les constructeurs A (alternatif), L (littéral), T (puis) et E (vide / epsilon). Le 'Star' habituel n'apparaît pas parce que je l'inline en alternance pendant l'analyse (voir '%'). 'm' exécute la simulation. L'analyseur (commencer à 'rs = ....') n'est qu'une descente récursive; «k» analyse les plages. La fonction '#' étend les plages en alternances.
la source
Python v2.7
10691036950925897884871833822Cette réponse semble assez longue pour un golf de code, mais il y a beaucoup d'opérateurs qui doivent être traités et je sais à quoi sert chaque octet de cette réponse. Puisqu'il n'y a pas de réponse existante, je soumets cela comme un objectif à battre pour les autres utilisateurs. Voyez si vous pouvez faire une réponse plus courte :).
Les deux fonctions principales sont celles
f
qui analysent l'expression rationnelle en commençant par lei
e caractère etd
qui génèrent les chaînes correspondantes, en utilisantr
les sous-expressions rationnelles dans lesquelles nous pouvons récurser, `` a '' le tableau représentant la partie de la sous-expression rationnelle actuelle non encore traitée, et un suffixe de chaînes
qui représente la partie de la chaîne générée jusqu'à présent.Consultez également l' échantillon de sortie et un faisceau de test .
Notez que les onglets de la solution d'origine ont été
expand
édités. Pour compter le nombre de caractères dans l'utilisation d'origineunexpand < regex.py | wc
.la source
def E(a,b):c=a[:];c.extend(b);return c
pourE=lambda a,b:a[:].extend(b)
, idem pourA
elif isinstance(e,str):
, je pense que vous pouvez changer le code à l'intérieur en:exec{'.':'for c in C:d(r,p,s+chr(c))','?':'d(r,p,s);d(r,p[:z],s)','*':'''c=p[:z]#newline for i in R(0,n+1):d(r,c,s);c+=[p[z]]''','+':"d(r,p+['*',p[z]],s)",'\\':'d(r,p,e[1]+s)'}.get(e,'d(r,p,e+s)')
(notez que#newline
c'est une nouvelle ligne) (source: stackoverflow.com/a/103081/1896169 )Prolog (SWI) , 590 octets
La capacité de retour en arrière intégrée de Prolog en fait un choix génial pour ce défi. En tirant parti du retour arrière, la génération de chaînes pour une expression régulière devient exactement la même tâche que de tester si une chaîne est mise en correspondance par une expression régulière. Malheureusement, une grande partie de mon effort de golf a été consacrée à l'écriture d'analyseurs regex plus courts. La tâche réelle de décomposer une expression régulière, nous avons facilement joué au golf.
Le prédicat
-\3
peut être invoqué avec les deux premiers arguments instanciés pour générer les chaînes correspondant à une expression régulière.Essayez-le en ligne!
Code non golfé
la source