Regex Golf: Vérifier une solution de sudoku

65

Ecrivez une expression rationnelle qui correspond à toute solution de sudoku valide et ne correspond à aucune solution de sudoku non valide. L'entrée est une version non déroulée du sudoku, c'est-à-dire qu'il n'y a pas de séparateur de ligne. Par exemple, le tableau suivant:

7 2 5 8 9 3 4 6 1
8 4 1 6 5 7 3 9 2
3 9 6 1 4 2 7 5 8
4 7 3 5 1 6 8 2 9
1 6 8 4 2 9 5 3 7
9 5 2 3 7 8 1 4 6
2 3 4 7 6 1 9 8 5
6 8 7 9 3 5 2 1 4
5 1 9 2 8 4 6 7 3

serait donné comme:

725893461841657392396142758473516829168429537952378146234761985687935214519284673

Les règles sont probablement de notoriété publique à l'heure actuelle, mais juste au cas où ... un conseil de sudoku est valide si et seulement si:

  • Chaque ligne contient les chiffres de 1à 9exactement une fois.
  • Chaque colonne contient les chiffres de 1à 9exactement une fois.
  • Chacune des neuf sous-réseaux 3x3 contient les chiffres de 1à 9exactement une fois.

Règles

Votre réponse doit consister en une seule expression rationnelle, sans aucun code supplémentaire (à l'exception, éventuellement, d'une liste de modificateurs d'expression régulière nécessaires pour faire fonctionner votre solution). Vous ne devez pas utiliser les fonctionnalités de la version regex de votre langue qui vous permettent d'appeler du code dans la langue de l'hébergement (par exemple, le emodificateur de Perl ).

Vous pouvez utiliser n’importe quel goût de regex qui existait avant ce défi, mais veuillez le spécifier.

Ne supposez pas que l'expression régulière est ancrée implicitement. Par exemple, si vous utilisez Python, supposez que votre expression rationnelle est utilisée avec re.searchet non avec re.match. Votre regex n'a pas besoin de correspondre à la chaîne entière. Il doit simplement faire correspondre au moins une sous-chaîne (qui peut être vide) pour des solutions valides et ne donner aucune correspondance pour des solutions non valides.

Vous pouvez supposer que l'entrée sera toujours une chaîne de 81 chiffres positifs.

C'est le regex golf, donc le regex le plus court en octets gagne. Si votre langue nécessite des délimiteurs (généralement /.../) pour désigner les expressions régulières, ne comptez pas les délimiteurs eux-mêmes. Si votre solution nécessite des modificateurs, ajoutez un octet par modificateur.

Cas de test

Conseils valides:

123456789456789123789123456231564897564897231897231564312645978645978312978312645
725893461841657392396142758473516829168429537952378146234761985687935214519284673
395412678824376591671589243156928437249735186738641925983164752412857369567293814
679543182158926473432817659567381294914265738283479561345792816896154327721638945
867539142324167859159482736275398614936241587481756923592873461743615298618924375
954217683861453729372968145516832497249675318783149256437581962695324871128796534
271459386435168927986273541518734269769821435342596178194387652657942813823615794
237541896186927345495386721743269158569178432812435679378652914924813567651794283
168279435459863271273415986821354769734692518596781342615947823387526194942138657
863459712415273869279168354526387941947615238138942576781596423354821697692734185
768593142423176859951428736184765923572389614639214587816942375295837461347651298
243561789819327456657489132374192865926845317581673294162758943735914628498236571
243156789519847326687392145361475892724918653895263471152684937436729518978531264
498236571735914628162758943581673294926845317374192865657489132819327456243561789
978531264436729518152684937895263471724918653361475892687392145519847326243156789
341572689257698143986413275862341957495726831173985426519234768734869512628157394

Planches non valides:

519284673725893461841657392396142758473516829168429537952378146234761985687935214
839541267182437659367158924715692843624973518573864192298316475941285736456729381
679543182158926473432817659567381294914256738283479561345792816896154327721638945
867539142324167859159482736275398684936241517481756923592873461743615298618924375
754219683861453729372968145516832497249675318983147256437581962695324871128796534
271459386435168927986273541518734269769828435342596178194387652657942813823615794
237541896186927345378652914743269158569178432812435679495386721924813567651794283
168759432459613278273165984821594763734982516596821347615437829387246195942378651
869887283619214453457338664548525781275424668379969727517385163319223917621449519
894158578962859187461322315913849812241742157275462973384219294849882291119423759
123456789456789123564897231231564897789123456897231564312645978645978312978312645
145278369256389147364197258478512693589623471697431582712845936823956714931764825
243561789829317456657489132374192865916845327581673294162758943735924618498236571
243156789529847316687392145361475892714928653895263471152684937436719528978531264
498236571735924618162758943581673294916845327374192865657489132829317456243561789
978531264436719528152684937895263471714928653361475892687392145529847316243156789
342571689257698143986413275861342957495726831173985426519234768734869512628157394
345678192627319458892451673468793521713524986951862347179246835534187269286935714
341572689257698143986413275862341957495726831173985426519234768734869512628517394

Pour les autres cas de test, vous pouvez utiliser ce script CJam qui prend un tableau valide en entrée et le mélange de manière aléatoire pour donner un nouveau tableau valide (format d’entrée non pertinent tant qu’il ne contient que des chiffres et éventuellement des espaces).

Si votre expression rationnelle est compatible avec la version .NET, vous pouvez la tester en ligne avec Retina. Une solution valide doit imprimer 0pour les cartes non valides et un nombre entier positif pour les cartes valides. Pour exécuter tous les scénarios de test en même temps, utilisez ce modèle et insérez l'expression régulière sur la deuxième ligne. Si vous avez besoin de modificateurs de regex, ajoutez a `à la regex et mettez les lettres de modificateur standard devant.

Martin Ender
la source
1
Si seulement c'était [code-bowling], lol.
mbomb007
Attendez ... Si nous utilisons Python, nous pouvons uniquement utiliser des expressions régulières, et rien d' autre? Aussi, quelle est la taille de chaque conseil? Y a-t-il une taille spécifique? Si non, comment devrions-nous extraire chaque tableau du groupe de chiffres sous valid boards?
R. Kap
@ R.Kap Peu importe la saveur que vous utilisez, vous ne devez envoyer que les regex (et éventuellement certains modificateurs), oui. Chaque entrée comprend exactement 81 chiffres et représente un tableau complet. (Chaque ligne dans les cas de test constitue un tableau séparé.)
Martin Ender
J'ai écrit un script pour résoudre des sudoku simples en SQL. Je suis sûr que cela peut être réécrit pour cette question. Cependant, SQL n'a pas beaucoup de REGEX. Est-ce que cela disqualifie la réponse? (Le script serait probablement un peu en dessous de 400 caractères)
t-clausen.dk

Réponses:

40

Ruby regex, 71 78 73 octets

^(?!.*(?=(.))(.{9}+|(.(?!.{9}*$))+|(?>.(?!.{3}*$)|(.(?!.{27}*$)){7})+)\1)

Je ne connais pas vraiment Ruby, mais apparemment, il ne se plaint pas des quantificateurs en cascade.

Essayez-le ici.

Regex .NET, 79 78 75 ou 77 octets

Parce que Martin pense que c'est possible ... Mais je suppose qu'il va simplement incorporer ces changements aussi.

^(?!(.)+((.{9})+|(?>(.{9})+
|.)+|(?((...)*
)(?>(.{27})+
|.){7}|.)+)(?<=\1))

Nécessite un retour à la ligne dans l'entrée pour fonctionner. Je ne suis pas sûr d'avoir le droit de le faire (probablement pas).

Essayez-le ici.

La version saine de 77 octets:

^(?!(.)+((.{9})+|((?!(.{9})*$).)+|(?((...)*$)((?!(.{27})*$).){7}|.)+)(?<=\1))

Merci Neil d’avoir signalé l’erreur dans ma version précédente et de jouer au golf de 1 octet (pour le (...)*).

Essayez-le ici.

PCRE, 77 78 octets

^(?!.*(?=(.))((.{9})+|(.(?!(?3)*$))+|(?(?=.(...)*$)(.(?!(.{27})*$)){7}|.)+)\1)

Juste pour être complet.

Essayez-le ici.

Une autre version, également 78 octets:

^(?!.*(?=(.))((.{9})+|(.(?!(?3)*$))+|(?>.(?!(...)*$)|(.(?!(.{27})*$)){7})+)\1)

Essayez-le ici.

Explication

^(?!.*                    # Match a string that doesn't contain the pattern,
                          # at any position.
  (?=(.))                 # Capture the next character.
  (
    (.{9})+               # Any 9*n characters. The next character is in
                          # the same column as the captured one.
  |
    (.(?!(.{9})*$))+      # Any n characters not followed by a positions 9*m
                          # to the end. The next character is in the same row
                          # as the captured one.
  |
    (                     # Any n occasions of...
    ?(.(...)*$)           # If it is at a position 3*k+1 to the end:
      (.(?!(.{27})*$)){7} # Then count 7*m characters that are not followed
                          # by a position 27*j to the end,
    |
      .                   # Else count any character.
    )+                    # The next character is in the same block as the
                          # captured one.
  )
  \1                      # Fail if the next character is the captured character.
)
jimmy23013
la source
Wow beau travail. Je n'ai eu que 83 dans .NET et j'ai dû passer à PCRE pour 78. Je ne doute pas que vous finirez par battre aussi. :)
Martin Ender
@ MartinBüttner Yep.
Nic Hartley
Je pensais que mon utilisation de lookahead pour battre @ MartinBüttner par (à l'époque) 4 octets était bien, mais vous avez porté cela à un niveau supérieur.
Neil
Désolé, mais cela ne détecte pas si les cellules en (1, 2) et (2, 1) sont identiques, et de la même manière pour toutes les autres cellules des carrés où la copie est en bas et à gauche.
Neil
1
@ MartinBüttner Je viens de me rendre compte que je peux traduire ma deuxième version PCRE en Ruby ... Je suppose que vous pouvez poster votre réponse maintenant ...
jimmy23013
34

PCRE, 117 119 130 133 147 octets

^(?!(.{27})*(...){0,2}(.{9})?.?.?(.).?.?(?=(?2)*$).{6,8}(?3)?\4.{0,17}(?1)*$|.*(.)(.{8}(?3)*|((?!(?3)*$)(|.(?7))))\5)

Devrait également fonctionner dans les saveurs Python, Java, etc. Maintenant avec récursion! Et la fonctionnalité "récursion" utilisée de manière non récursive pour les "sous-programmes", que j'ai totalement oubliée jusqu'à ce que je devais utiliser la récursivité réelle.

feersum
la source
Idée géniale - évitez les répétitions au lieu de faire correspondre les norepeats!
Qwertiy
1
C'est dommage que vous ne puissiez pas écrire .{27}*.
Neil
Bah, j'avais golfé votre solution de 133 octets à 121 octets seulement pour constater que vous l'aviez réécrite, mais la voici quand même:^(?!(.{27})*(.{9})?(...){0,2}.?.?(.).?.?(?=(...)*$)(.{9})?.{6,8}\4.{0,17}(.{27})*$|.*(.)((.{9})+|((?!(.{9})*$).)+)(<=\8))
Neil
@ Neil Quelle saveur est-ce? PCRE ou d’autres que je connais ne permettent pas les références arrières dans une recherche.
Feersum
@Neil (<=\8)ne ressemble pas à une syntaxe valide (il manque un ?). En outre, la seule variante que je connaisse qui prenne en charge les références arrières dans les références externes est .NET.
Martin Ender
15

Regex .NET, 8339 octets

Oui, je sais que ma solution est très naïve, puisque Martin m'a dit qu'il l'avait fait dans environ 130 octets. En fait, l'URL pour essayer en ligne est si longue que je ne pouvais pas trouver un raccourcisseur d'URL qui l'accepterait.

(code removed, since it's so long nobody will read it here, 
and it made the post take forever to load. Just use the "Try it online" link.)

Le lien ci-dessous ne fonctionne pas dans IE, mais dans Chrome et Firefox.

Essayez-le en ligne - Tous les cas de test à la fois, avec l'aide du!`début, ne sont pas inclus dans le nombre d'octets.


Voici le script Python que j'ai utilisé pour le générer (code ci-dessous):

R=range(0,9)
S=range(1,10)

o = ""

# validate rows
T = "(?=.{%s,%s}%s)"
for j in R:
    for i in S:
        o += T % (9*j,9*(j+1)-1, i)

# validate columns
# "(?=(.{%s}|.{%s}|.{%s}|.{%s}|.{%s}|.{%s}|.{%s}|.{%s}|.{%s})%s)"
T = "(?=("+"|".join([".{%s}"]*9)+")%s)"
for j in R:
    for i in S:
        o += T % (j,j+9,j+18,j+27,j+36,j+45,j+54,j+63,j+72, i)

# validate boxes
# (?=.{0,2}1|.{9,11}1|.{18,20}1)(?=.{3,5}1|.{12,14}1|.{21,23}1)
# (?=.{27,29}1|.{36,38}1|.{45,47}1)
T = ".{%s,%s}%s"
for i in S:
    for x in (0,27,54):
        for y in (0,3,6):
            o += "(?="+"|".join(T % (x+y+z,x+y+z+2, i) for z in (0,9,18))+")"

o += ".{81}"

o = o.replace(".{0}","").replace(",80}",",}")
print(o)
mbomb007
la source
1
Je te
Martijn
4
Savoir ce qui est drôle? Le lien en ligne try it plantera IE parce que c'est trop long: P
cat le
15
@cat C'est pourquoi le seul objectif réel d'IE est de permettre à l'utilisateur de télécharger Firefox (ou Chromium).
Byte Commander
2
@cat Cela ne bloque pas IE11 sous Windows 8.1, bien que la Regex ne soit pas traitée correctement.
Nzall
2
@cat Cela ne plante pas IE 11 sur Windows 7. Cela ne fait que tronquer l'URL.
mbomb007
14

Regex .NET, 121 octets

^(?!(.{27})*(.{9})?(...){0,2}.?.?(.).?.?(?=(...)*$)(.{9})?.{6,8}\4.{0,17}(.{27})*$|.*(?=(.))((.{9})+|(.(?!(.{9})*$))+)\8)

Explication:

^(?!                     Invert match (because we're excluding duplicates)
 (.{27})*                Skip 0, 3 or 6 rows
 (.{9})?                 Optionally skip another row
 (...){0,2}              Skip 0, 3 or 6 columns
 .?.?(.).?.?(?=(...)*$)  Choose any of the next three cells
 (.{9})?                 Optionally skip another row
 .{6,8}\4                Match any of the three cells below
 .{0,17}(.{27})*$        As long as they're from the same square
|                        OR
 .*(?=(.))(              Choose any cell
  (.{9})+                Skip at least one row
 |                       or
  (.                     Skip cells
   (?!(.{9})*$)          Without reaching the end of the row
  )+                     For at least one cell (i.e. the cell chosen above)
 )\8)                    Match the chosen cell to the next cell
)
Neil
la source
Nice, votre combinaison de lignes et de colonnes est assez astucieuse. Cela économise 4 octets sur ma propre solution. :)
Martin Ender
8

PCRE, 3579 octets

Une solution de force brute absolument terrible. Regard négatif négatif ahoy!

J'ai passé trop de temps là-dessus pour l'abandonner, alors voila, pour la postérité.

D'un autre côté, si Sudoku commence soudainement à utiliser un ensemble différent de 9 caractères, cela fonctionnera toujours, je suppose ...

http://pastebin.com/raw/CwtviGkC

Je ne sais pas comment utiliser Retina, mais vous pouvez également le coller dans https://regex101.com ou similaire pour que cela corresponde.

Code Ruby utilisé pour générer la regex:

# Calculate the block you're in
def block(x)
    x /= 3
    x + x%3 - x%9
end

81.times do |i|
    row, col = i.divmod(9)
    neg = []
    neg += (0...col).map {|e| 9*row + e + 1}
    neg += (0...row).map {|e| 9*e + col + 1}
    neg += (0...i).map {|e| e + 1 if block(e) == block(i)}.compact
    neg = neg.uniq.sort.map {|e| "\\#{e}"}
    if neg.size > 0
        print "(?!#{neg.join '|'})"
    end
    print "(.)"
end
Valeur d'encre
la source
8

Saveur de rubis, 75 à 74 octets

Merci à jimmy23013 d’avoir économisé 1 octet.

^(?!(.{9}*(.|(.)){,8}|.*(\g<2>.{8})*|.{27}?.{3}?(\g<2>{3}.{6}){,2}.?.?)\3).

Testez-le ici.

Maintenant que c'est enfin vaincu, je peux partager ma propre solution. :) J'ai découvert une technique de regex intéressante (peut-être nouvelle?) Dans le processus (la (.|(.)){,8}\3partie), qui serait probablement imbattable dans les cas où cela ne peut pas être combiné avec d'autres parties de la regex (comme ce fut le cas dans la réponse de jimmy23013) .

Explication

Comme les autres réponses brèves, j'utilise un indicateur négatif qui recherche les doublons dans les lignes, les colonnes ou les blocs. Le composant de base de la solution est le suivant:

(.|(.))...\3

Notez que le \3est réutilisé entre trois alternatives différentes (qui utilisent toutes un groupe 3pour la détection des doublons).

Ce groupe de gauche (groupe 2, groupe contenant 3) est utilisé pour toute position pouvant contenir la première moitié d'un chiffre en double (au sein d'un groupe ne devant pas contenir de chiffres en double). Vient ensuite ...quelque chose qui nous amène à la position suivante où un tel chiffre peut apparaître (si nécessaire) et \3tente de trouver la seconde moitié de la copie via backreference. La raison pour laquelle cela fonctionne est un retour en arrière. Lorsque le moteur correspond pour la première fois, (.|(.))il utilisera simplement à .chaque fois et ne capturera rien. Maintenant la \3fin échoue. Mais maintenant, le moteur va progressivement essayer d’utiliser (.)plutôt que .pour des matches individuels. En fin de compte, s'il y a un doublon, il trouvera la combinaison où(.)a été utilisé pour la dernière fois sur le premier chiffre du duplicata (de telle sorte que la capture ne soit pas écrasée ultérieurement), puis utilise un peu plus .pour réduire l'écart vers la référence arrière. S'il y a un doublon, le retour en arrière le trouvera toujours.

Regardons les trois parties différentes où cela est utilisé:

.{9}*(.|(.)){,8}

Ceci vérifie les doublons dans une ligne. D'abord, nous passons à n'importe quelle ligne avec .{9}*. Nous comparons ensuite jusqu'à 8 caractères (c’est-à-dire tout ce qui se trouve dans cette ligne, à l’exception du dernier chiffre) à l’aide de la copie facultative de la copie, puis nous essayons de trouver l’ \3après.

.*(\g<2>.{8})*

Cela cherche des doublons dans certaines colonnes. Tout d’abord, notez qu’il \g<2>s’agit d’un appel à un sous-programme, c’est la même chose que:

.*((.|(.)).{8})*

où les deux groupes que nous venons d'insérer sont encore appelés 2et 3.

Ici, on .*saute simplement autant que nécessaire (il suffirait de faire correspondre jusqu'à 8 caractères ici, mais cela coûte plus d'octets). Ensuite, le groupe externe correspond à une ligne complète (qui peut se chevaucher sur deux lignes physiques) à la fois, capturant éventuellement le premier caractère. Le \3sera recherché juste après, ce qui assure un alignement vertical entre la capture et la référence arrière.

Enfin, vérifiant les blocs:

.{27}?.{3}?(\g<2>{3}.{6}){,2}.?.?

Encore une fois, il \g<2>s’agit d’un appel de sous-programme, c’est la même chose que:

.{27}?.{3}?((.|(.)){3}.{6}){,2}.?.?

Pour vérifier les blocs, notez que puisque nous avons déjà vérifié toutes les lignes et toutes les colonnes, nous n'avons besoin que de vérifier quatre des blocs 3x3. Quand on sait que toutes les lignes et colonnes ainsi que ces blocs 3x3 sont corrects:

XX.
XX.
...

Ensuite, nous savons qu'il ne peut pas y avoir de doublons dans les blocs restants. Par conséquent, je ne vérifie que ces quatre blocs. De plus, notez qu'il n'est pas nécessaire de rechercher des doublons dans la même ligne d'un bloc 3x3. Il suffit de trouver la première moitié du duplicata dans une rangée et de rechercher la seconde moitié de suite.

Maintenant pour le code lui-même, nous allons d’abord au début de l’un des quatre blocs avec .{27}?.{3}?(éventuellement sauter trois lignes, éventuellement trois colonnes). Ensuite, nous essayons de faire correspondre jusqu'à deux des lignes du bloc 3x3 avec le même truc que celui utilisé précédemment pour les lignes:

(.|(.)){3}.{6}

Nous autorisons, mais n'exigeons pas, la capture de l'une des 3 cellules de la ligne actuelle du bloc 3x3, puis passons à la ligne suivante avec .{6}. Enfin, nous essayons de trouver un doublon dans l’une ou l’autre des 3 cellules de la ligne sur laquelle nous nous retrouvons:

.?.?

Et c'est tout.

Martin Ender
la source
74 ^(?!(.*((.|(.)).{8})*|.{9}*\g<3>{,8}|.{27}?.{3}?(\g<3>{3}.{6}){,2}.?.?)\4):; 73: ^(?!(.*((.|(.)|\4()).{8})*|.{9}*\g<3>{9}|.{27}?.{3}?(\g<3>{3}.{6}){3})\5).
Jimmy23013
@ jimmy23013 J'utilisais le \4()truc dans une version antérieure pour les blocs 3x3, mais j'ai fini par m'en débarrasser, parce que c'était plus long. : D
Martin Ender
@ jimmy23013 Le 73 ne vérifie pas la dernière ligne:341572689257698143986413275862341957495726831173985426519234768734869512628517394
Martin Ender
6

Javascript regex, 532 530 481 463 caractères

Valider les lignes:

/^((?=.{0,8}1)(?=.{0,8}2)(?=.{0,8}3)(?=.{0,8}4)(?=.{0,8}5)(?=.{0,8}6)(?=.{0,8}7)(?=.{0,8}8)(?=.{0,8}9).{9})+$/

Valider les colonnes:

/^((?=(.{9}){0,8}1)(?=(.{9}){0,8}2)(?=(.{9}){0,8}3)(?=(.{9}){0,8}4)(?=(.{9}){0,8}5)(?=(.{9}){0,8}6)(?=(.{9}){0,8}7)(?=(.{9}){0,8}8)(?=(.{9}){0,8}9).){9}/

Valider le carré à partir de son premier caractère:

/(?=.?.?(.{9}){0,2}1)(?=.?.?(.{9}){0,2}2)(?=.?.?(.{9}){0,2}3)(?=.?.?(.{9}){0,2}4)(?=.?.?(.{9}){0,2}5)(?=.?.?(.{9}){0,2}6)(?=.?.?(.{9}){0,2}7)(?=.?.?(.{9}){0,2}8)(?=.?.?(.{9}){0,2}9)/

Définissez l'aperçu au début du carré:

/^(((?=)...){3}.{18})+$/

Et toute l'expression:

/^(?=((?=.{0,8}1)(?=.{0,8}2)(?=.{0,8}3)(?=.{0,8}4)(?=.{0,8}5)(?=.{0,8}6)(?=.{0,8}7)(?=.{0,8}8)(?=.{0,8}9).{9})+$)(?=((?=(.{9}){0,8}1)(?=(.{9}){0,8}2)(?=(.{9}){0,8}3)(?=(.{9}){0,8}4)(?=(.{9}){0,8}5)(?=(.{9}){0,8}6)(?=(.{9}){0,8}7)(?=(.{9}){0,8}8)(?=(.{9}){0,8}9).){9})(((?=.?.?(.{9}){0,2}1)(?=.?.?(.{9}){0,2}2)(?=.?.?(.{9}){0,2}3)(?=.?.?(.{9}){0,2}4)(?=.?.?(.{9}){0,2}5)(?=.?.?(.{9}){0,2}6)(?=.?.?(.{9}){0,2}7)(?=.?.?(.{9}){0,2}8)(?=.?.?(.{9}){0,2}9)...){3}.{18})+$/

Correspond à la chaîne entière.


Test en Javascript ES6:

r = /^(?=((?=.{0,8}1)(?=.{0,8}2)(?=.{0,8}3)(?=.{0,8}4)(?=.{0,8}5)(?=.{0,8}6)(?=.{0,8}7)(?=.{0,8}8)(?=.{0,8}9).{9})+$)(?=((?=(.{9}){0,8}1)(?=(.{9}){0,8}2)(?=(.{9}){0,8}3)(?=(.{9}){0,8}4)(?=(.{9}){0,8}5)(?=(.{9}){0,8}6)(?=(.{9}){0,8}7)(?=(.{9}){0,8}8)(?=(.{9}){0,8}9).){9})(((?=.?.?(.{9}){0,2}1)(?=.?.?(.{9}){0,2}2)(?=.?.?(.{9}){0,2}3)(?=.?.?(.{9}){0,2}4)(?=.?.?(.{9}){0,2}5)(?=.?.?(.{9}){0,2}6)(?=.?.?(.{9}){0,2}7)(?=.?.?(.{9}){0,2}8)(?=.?.?(.{9}){0,2}9)...){3}.{18})+$/
;`123456789456789123789123456231564897564897231897231564312645978645978312978312645
725893461841657392396142758473516829168429537952378146234761985687935214519284673
395412678824376591671589243156928437249735186738641925983164752412857369567293814
679543182158926473432817659567381294914265738283479561345792816896154327721638945
867539142324167859159482736275398614936241587481756923592873461743615298618924375
954217683861453729372968145516832497249675318783149256437581962695324871128796534
271459386435168927986273541518734269769821435342596178194387652657942813823615794
237541896186927345495386721743269158569178432812435679378652914924813567651794283
168279435459863271273415986821354769734692518596781342615947823387526194942138657
863459712415273869279168354526387941947615238138942576781596423354821697692734185
768593142423176859951428736184765923572389614639214587816942375295837461347651298`
.split`
`.every(r.test.bind(r))
&&
`519284673725893461841657392396142758473516829168429537952378146234761985687935214
839541267182437659367158924715692843624973518573864192298316475941285736456729381
679543182158926473432817659567381294914256738283479561345792816896154327721638945
867539142324167859159482736275398684936241517481756923592873461743615298618924375
754219683861453729372968145516832497249675318983147256437581962695324871128796534
271459386435168927986273541518734269769828435342596178194387652657942813823615794
237541896186927345378652914743269158569178432812435679495386721924813567651794283
168759432459613278273165984821594763734982516596821347615437829387246195942378651
869887283619214453457338664548525781275424668379969727517385163319223917621449519
894158578962859187461322315913849812241742157275462973384219294849882291119423759
123456789456789123564897231231564897789123456897231564312645978645978312978312645
145278369256389147364197258478512693589623471697431582712845936823956714931764825`
.split`
`.every(s => !r.test(s))
Qwertiy
la source
Je pense que les colonnes devraient être beaucoup plus faciles que les lignes, je trouve donc curieux que votre regex de colonne soit plus long que votre première ligne.
Peter Taylor
@PeterTaylor, ils ont la même structure, mais pour les colonnes, je dois sauter 9 caractères au lieu de 1, donc .entre (.{9})avec des crochets à cause du suivant {0,8}. Pourquoi pensez-vous que les colonnes devraient être plus courtes?
Qwertiy
@PeterTaylor, oui, les colonnes auraient été plus simples si j'avais deviné vérifier la négation.
Qwertiy
@ SuperJedi224, pourquoi javascript? Je m'attends à ce que cette regex soit valable partout.
Qwertiy
6
@Qwertiy Alors que votre expression rationnelle devrait fonctionner dans de nombreuses variantes, elle repose sur des antécédents de look (non disponible dans Lua ou OCaml, par exemple). C'est également une expression régulière de base ou étendue non valide, qui utilise une syntaxe totalement différente. Il est préférable de choisir la saveur pour la revendication de validité, même si la solution fonctionne dans de nombreuses autres.
Dennis