Solution originale: JavaScript - 261 255 228 227 179 153 caractères
/(\d)(\1(\d|.{6}|.{9})|(\d|.{6}|.{9})\1|.{7}\1(.|.{9})|(.|.{9})\1.{7}|(.{7,9}|.{17})\1.{8}|.{8}\1(.{7,9}|.{17}))\1/.test(s.replace(/\n/g,'A'))?'yes':'no'
En supposant que la chaîne à tester se trouve dans la variable s
(pour en faire une fonction, f
ajoutez-la f=s=>
au début du code ou, sinon, prenez l'entrée d'une invite, puis remplacez-la s
par prompt()
).
Les sorties sont vers la console.
3 e solution: JavaScript (ECMAScript 6) - 178 caractères
p=x=>parseInt(x,36);for(t="2313ab1b8a2a78188h9haj9j8iaiir9r",i=v=0;s[i];i++)for(j=0;t[j];v|=s[i]==s[i+a]&s[i]==s[i+b]&i%9<8&(b>3|(i+b-a)%9<8))a=p(t[j++]),b=p(t[j++]);v?'yes':'no'
J'ai pris la 2 e solution ci-dessous (qui utilise des expressions régulières pour vérifier les caractères dans certaines configurations) et l' ai retravaillée pour simplement vérifier la chaîne pour des caractères identiques dans les mêmes configurations sans utiliser d'expressions régulières.
La chaîne Base-36 "2313ab1b8a2a78188h9haj9j8iaiir9r"
donne des paires de décalages à vérifier - c'est-à-dire que la paire 23
entraîne la vérification si le i ème caractère est identique au (i + 2) ème caractère et au (i + 3) ème caractère (l'équivalent de l'expression régulière (.).\1\1
- avec quelques vérifications supplémentaires pour s'assurer que le caractère non identique n'est pas une nouvelle ligne).
2 e solution: JavaScript (ECMAScript 6) - 204 caractères
p=x=>parseInt(x,18);g=a=>a?a>1?"(.|\\n){"+a+"}":".":"";f=(x,a,b)=>RegExp("(.)"+g(a)+"\\1"+g(b)+"\\1").test(x);for(t="10907160789879h8",i=v=0;t[i];v|=f(s,x,y)||f(s,y,x))x=p(t[i++]),y=p(t[i++]);v?'yes':'no'
Construit plusieurs expressions régulières (voir ci-dessous pour plus de détails) à l'aide de paires de valeurs tirées de la chaîne Base-18 10907160789879h8
et effectue OR
tous les tests. Pour le réduire davantage, vous pouvez noter que les expressions régulières viennent par paires où l'une est le «contraire» de l'autre (en ignorant les expressions régulières pour 3-in-a-row horizontalement et verticalement car l'OP indique qu'elles ne seront jamais présentes - si vous souhaitez ajouter ces tests dans l'annexe 0088
à la chaîne Base-18).
Explication
Commencez avec 16 expressions régulières couvrant toutes les configurations possibles de mouvements valides:
REs=[
/(\d)\1\1/, // 3-in-a-row horizontally
/(\d).\1\1/, // 3-in-a-row horizontally after left-most shifts right
/(\d)\1.\1/, // 3-in-a-row horizontally after right-most shifts left
/(\d)(?:.|\n){9}\1\1/, // 3-in-a-row horizontally after left-most shifts down
/(\d)(?:.|\n){7}\1.\1/, // 3-in-a-row horizontally after middle shifts down
/(\d)(?:.|\n){6}\1\1/, // 3-in-a-row horizontally after right-most shifts down
/(\d)\1(?:.|\n){6}\1/, // 3-in-a-row horizontally after left-most shifts up
/(\d).\1(?:.|\n){7}\1/, // 3-in-a-row horizontally after middle shifts up
/(\d)\1(?:.|\n){9}\1/, // 3-in-a-row horizontally after right-most shifts up
/(\d)(?:.|\n){7,9}\1(?:.|\n){8}\1/, // 3-in-a-row vertically (with optional top shifting left or right)
/(\d)(?:.|\n){7}\1(?:.|\n){9}\1/, // 3-in-a-row vertically after middle shifts right
/(\d)(?:.|\n){9}\1(?:.|\n){7}\1/, // 3-in-a-row vertically after middle shifts left
/(\d)(?:.|\n){8}\1(?:.|\n){7}\1/, // 3-in-a-row vertically after bottom shifts right
/(\d)(?:.|\n){8}\1(?:.|\n){9}\1/, // 3-in-a-row vertically after bottom shifts left
/(\d)(?:.|\n){17}\1(?:.|\n){8}\1/, // 3-in-a-row vertically after top shifts down
/(\d)(?:.|\n){8}\1(?:.|\n){17}\1/, // 3-in-a-row vertically after bottom shifts up
];
( Remarque: les expressions rationnelles pour 3 rangées horizontalement (0 e ) et verticalement (partie du 9 e ) ne sont pas pertinentes car l'OP indique que les entrées correspondant à celles-ci ne seront jamais présentes. )
Tester chacun de ceux-ci par rapport à l'entrée déterminera si un déplacement valide de cette configuration peut être trouvé.
Cependant, les expressions régulières peuvent être combinées pour donner ces 6:
/(\d)(?:.|(?:.|\n){9}|(?:.|\n){6})?\1\1/ // Tests 0,1,3,5
/(\d)\1(?:.|(?:.|\n){9}|(?:.|\n){6})?\1/ // Tests 0,2,6,8
/(\d)(?:.|\n){7}\1(?:.|(?:.|\n){9})\1/ // Tests 4,10
/(\d)(?:.|(?:.|\n){9})\1(?:.|\n){7}\1/ // Tests 7,11
/(\d)(?:(?:.|\n){7,9}|(?:.|\n){17})\1(?:.|\n){8}\1/ // Tests 9,14
/(\d)(?:.|\n){8}\1(?:(?:.|\n){7,9}|(?:.|\n){17})\1/ // Tests 9a,12,13,15
Ceux-ci peuvent ensuite être combinés en une seule expression régulière:
/(\d)(?:.|(?:.|\n){9}|(?:.|\n){6})?\1\1|(\d)\2(?:.|(?:.|\n){9}|(?:.|\n){6})?\2|(\d)(?:.|\n){7}\3(?:.|(?:.|\n){9})\3|(\d)(?:.|(?:.|\n){9})\4(?:.|\n){7}\4|(\d)(?:(?:.|\n){7,9}|(?:.|\n){17})\5(?:.|\n){8}\5|(\d)(?:.|\n){8}\6(?:(?:.|\n){7,9}|(?:.|\n){17})\6/
Ce qui doit juste être testé par rapport à l'entrée.
Cas de test
Certains cas de test que d'autres personnes pourraient trouver utiles (ne sont pas conformes au format d'entrée consistant à n'utiliser que les chiffres 1 à 7, mais cela est facilement corrigé et ne constitue qu'une grille 8x4 - car c'est le minimum requis pour un test de toutes les entrées valides ).
Au format d'une carte de la chaîne d'entrée à laquelle des 16 expressions régulières ci-dessus elle correspond.
Tests={
"12345678\n34567812\n56781234\n78123456": -1, // No Match
"12345678\n34969912\n56781234\n78123456": 1, // 3-in-a-row horizontally after left-most shifts right
"12345678\n34567812\n59989234\n78123456": 2, // 3-in-a-row horizontally after right-most shifts left
"12345978\n34567899\n56781234\n78123456": 3, // 3-in-a-row horizontally after left-most shifts down
"12345978\n34569892\n56781234\n78123456": 4, // 3-in-a-row horizontally after middle shifts down
"12345678\n34967812\n99781234\n78123456": 5, // 3-in-a-row horizontally after right-most shifts down
"12399678\n34967812\n56781234\n78123456": 6, // 3-in-a-row horizontally after left-most shifts up
"12345678\n34597912\n56789234\n78123456": 7, // 3-in-a-row horizontally after middle shifts up
"12345998\n34567819\n56781234\n78123456": 8, // 3-in-a-row horizontally after right-most shifts up
"12945678\n34597812\n56791234\n78123456": 9, // 3-in-a-row vertically after top shifts right
"12349678\n34597812\n56791234\n78123456": 9, // 3-in-a-row vertically after top shifts left
"12345978\n34569812\n56781934\n78123456": 10, // 3-in-a-row vertically after middle shifts right
"92345678\n39567812\n96781234\n78123456": 11, // 3-in-a-row vertically after middle shifts left
"12945678\n34967812\n59781234\n78123456": 12, // 3-in-a-row vertically after bottom shifts right
"12349678\n34569812\n56781934\n78123456": 13, // 3-in-a-row vertically after bottom shifts left
"12395678\n34567812\n56791234\n78193456": 14, // 3-in-a-row vertically after top shifts down
"12345698\n34567892\n56781234\n78123496": 15, // 3-in-a-row vertically after bottom shifts up
"12345678\n34567899\n96781234\n78123456": -1, // No match - Matches (.)\1.\1 but not 3 in a row
"12345679\n99567812\n56781234\n78123456": -1, // No match - Matches (.).\1\1 but not 3 in a row
};
Modifier 1
Remplacer \d
s par .
- enregistre 6 caractères.
Modifier 2
Remplacer (?:.|\n)
par [\s\S]
et groupes non enlevés de capture supplémentaires et des références arrières mises à jour (comme suggéré par m-Buettner ) et ajouté dans oui / non sortie.
Modifier 3
- Ajout de la solution ECMAScript 6 pour construire les expressions régulières individuelles à partir d'une chaîne Base-18.
- Suppression des tests pour 3-in-a-row horizontalement (comme suggéré par m-buettner ).
Modifier 4
Ajout d'une autre solution (plus courte) et de deux autres cas de tests non correspondants.
Modifier 5
- Solution originale raccourcie en remplaçant les sauts de ligne par un caractère non numérique (comme suggéré par VadimR ).
Modifier 6
- Solution originale raccourcie en combinant des bits de l'expression régulière (comme suggéré par VadimR ).