Il est facile de décrire une machine à états finis qui reconnaît les multiples de 9: gardez une trace de la somme des chiffres (mod 9) et ajoutez le chiffre qui sera accepté ensuite. Un tel FSM n'a que 9 états, très simple! Par l'équivalence entre la reconnaissance des FSM et les langues régulières, il existe une expression régulière pour des multiples de 9. Cependant, une telle expression régulière est probablement ... très ... longue. Comme dans, probablement de l'ordre d'un gigaoctet.
Il y a un exemple travaillé sur https://www.quaxio.com/triple/ pour des multiples de 3. En bas de la page, l'auteur fournit une solution quelque peu "optimisée à la main" qui est un peu plus courte que la conversion naïve de FSM à regex.
Le défi:
Vous devez créer une expression régulière pour détecter des multiples de 9. Puisqu'une telle expression régulière devrait être très longue, je vous demande de fournir un programme capable d'imprimer votre expression régulière. (Si vous voulez vraiment donner un regex entier, peut-être l'héberger ailleurs et le lier ici!)
Vous devez être en mesure de nous dire le nombre exact de caractères de la sortie de votre programme - donc avoir un programme qui essaie simplement toutes les expressions régulières jusqu'à une certaine longueur, jusqu'à ce qu'il en trouve un qui fonctionne, n'est acceptable que s'il s'exécute assez rapidement pour que vous puissiez exécutez-le jusqu'à la fin et donnez-nous la longueur d'expression régulière résultante!
Les points sont destinés à avoir l'expression rationnelle la plus courte, non basée sur la durée du programme, bien sûr. Étant donné que l'expression régulière est le "programme" que je demande, et qu'il est tout simplement trop long pour être transmis ici, je continue de baliser ce code-golf.
Règles:
- L'entrée comprendra uniquement les caractères correspondants
[0-9]*
. - Votre expression régulière doit correspondre à des multiples de 9, mais pas à autre chose. Les cas qui ne sont pas entièrement composés des chiffres 0 à 9 et qui sont des entrées non valides peuvent correspondre ou échouer comme vous le souhaitez.
- Étant donné la motivation qu'il est facilement reconnaissable par un DFA, l' expression régulière résultante doit en fait être une expression régulière dans la terminologie plus théorique, c'est-à-dire uniquement les opérateurs sous lesquels les langages réguliers sont fermés. Pour être précis, les seules choses autorisées:
- Littéraux, les chaînes de caractères (
[ab]
,[a-f]
,[^k]
), Kleene étoile (*
), points d' ancrage (^
et$
), le regroupement par parenthèses, l' alternance (|
), les termes en option (?
), un-ou-plus de termes (+
), lookaheads ((?=)
), lookaheads négative ((?!)
), lookbehinds ((?<=)
), lookbehinds négatifs ((?<!)
), conditionnels (comme dans https://www.regular-expressions.info/conditional.html -(?(?=test)then|else)
), et références inverses de longueur limitée (voir ci-dessous).
- Littéraux, les chaînes de caractères (
- Des exemples de choses qui ne sont pas autorisés:
- Références inverses de longueur arbitraire, références directes, récursivité, sous-programmes, constructions en boucle, code exécutable, toute variation de 'eval' ou constructions intégrées pour convertir la chaîne en une valeur arithmétique.
- Les références arrières dont on peut montrer qu'elles ont une chaîne de liaison de longueur limitée sont acceptables, car elles peuvent être stockées à l'état fini et ne modifient pas la régularité du langage. Par exemple, l'expression régulière
(..2.[3-5])4\1.\1
est acceptable, car il y a une longueur liée sur le groupe de capture\1
. Il s'agit d'une construction régulière. Une construction telle que(2*)0\1
n'est pas acceptable, car le groupe capturé ne peut pas être stocké dans un état fini. - Votre expression régulière est libre d'accepter ou de rejeter des entiers avec des zéros non significatifs comme vous le souhaitez. Cependant, la chaîne
"0"
doit être acceptée.
^(0|9|(?<c>1|(?<c>2|(?<c>3|(?<c>4|(?<c>5|(?<c>6|(?<c>7|(?<c>8))))))))((?<-c>){9})?)*$(?(c).)