Déterminer si un coup existe dans une partie Bejeweled / match 3

20

Contexte

Dans les jeux Bejeweled et similaires, le joueur doit échanger deux gemmes adjacentes (pas de diagonales) dans une grille de gemmes 8x8 afin de faire correspondre trois de la même couleur d'affilée. Les gemmes peuvent être assorties horizontalement ou verticalement. Le gameplay se poursuit jusqu'à ce qu'il n'y ait aucun mouvement qui puisse être effectué, résultant en trois de suite, à quel point le jeu est terminé.

Tâche

Le but est d'écrire un programme qui détermine si une partie de Bejeweled n'est pas encore terminée. En d'autres termes, il doit vérifier s'il y a un mouvement possible qui en fait au moins trois d'affilée. Il peut y avoir plus de trois gemmes d'affilée et c'est toujours un mouvement valide.

Contribution

Votre programme doit accepter via une entrée standard une représentation 8x8 d'une grille Bejeweled. Chacune des sept couleurs de gemmes sera représentée par un chiffre de 1 à 7. Chaque ligne contiendra une ligne et 8 lignes, chacune composée de 8 chiffres, seront entrées. Voir les exemples. Vous pouvez supposer que l'entrée suivra toujours ce format et n'en contiendra jamais trois de suite.

Production

Le programme doit ensuite sortir (vers la sortie standard) yesou noselon qu'il existe ou non au moins un mouvement valide qui entraînerait trois gemmes ou plus d'affilée. Votre programme ne doit rien produire d'autre qu'une seule instance de yesou no.

Règles

Votre programme ne doit pas utiliser de fichiers ou de ressources externes, d'arguments de ligne de commande ou exiger un certain nom de fichier. Le programme avec le moins d'octets dans son code source gagne.

Exemples

Contribution:

12314131
13224145
54762673
61716653
61341144
23453774
27645426
75575656

Production: yes

Contribution:

35261546
76421754
15743271
62135642
35617653
64565476
54427254
15635465

Production: no

Voir la réponse de MT0 ci-dessous pour des cas de test supplémentaires.

bdr9
la source
Est-ce seulement des lignes ou des colonnes?
TheDoctor
@TheDoctor Columns aussi. Lorsque j'utilise l'expression «trois de suite», je veux dire qu'ils doivent être alignés dans le sens horizontal ou vertical.
bdr9
@ bdr9 vous voudrez peut-être modifier cela dans
John Dvorak
@JanDvorak Done.
bdr9
Vous pouvez également vouloir modifier si 4+ d'affilée sont autorisés.
Justin

Réponses:

12

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, fajoutez-la f=s=>au début du code ou, sinon, prenez l'entrée d'une invite, puis remplacez-la spar 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 23entraî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 10907160789879h8et effectue ORtous 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 \ds 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 ).
MT0
la source
1
Bonne solution! Je n'aurais pas pensé que l'expression régulière pouvait fonctionner. Veuillez inclure le ?'yes':'no'dans votre nombre de caractères pour l'équité, car il est dans les exigences et tout le monde l'utilise.
bdr9
Merci pour les cas de test supplémentaires, j'ai ajouté un lien vers votre réponse afin que d'autres personnes puissent les voir.
bdr9
Whoa. +1 pour regex
DankMemes
H-mm, aucun modificateur dans JS pour .correspondre à n'importe quel caractère, y compris la nouvelle ligne? Avec Perl, l'expression rationnelle combinée n'est qu'une chaîne de 129 octets (que, étant paresseux, j'ai compilé avec Regexp :: Assemble ), donc le programme Perl entier fait environ 150 octets.
user2846289
1
@VadimR Merci mais vous pouvez aller encore plus loin en remplaçant .{8}|.{9}par .{8,9}et .{7}|.{8}avec.{7,8}
MT0
3

Python 383

Une seule * ligne de Python!

a=[list(l)for l in raw_input().split('\n')];z=any;e=enumerate;c=lambda b:z(all(p==b[y+v][x+u]for(u,v)in o)for y,r in e(b[:-2])for x,p in e(r[:-2])for o in [[(0,1),(0,2)],[(1,0),(2,0)]]);print z(c([[q if(i,j)==(m,n)else a[m][n]if(i,j)==(y+1,x+1)else p for j,p in e(r)]for i,r in e(a)])for y,t in e(a[1:-1])for x,q in e(t[1:-1])for n,m in((x+u,y+v)for u,v in[(1,0),(1,2),(0,1),(2,1)]))

* Eh bien, avec des points-virgules, mais ce n'est toujours pas trivial en python (les lignes simples en python sont amusantes! )

KSab
la source
3
A voté pour des compréhensions incompréhensibles :)
alexander-brett
2

Node.js - Solution naïve - 905 octets

Eh bien, pas encore de réponses donc je vais publier une solution vraiment naïve dans Node.js

Il passe par chaque mouvement possible et teste ensuite le tableau résultant pour voir s'il y a 3 d'affilée.

Golfé (avec compilateur de fermeture Google) (quelques trucs hacky comme! 0 et! 1; je ne suis même pas sûr de ce qu'il a fait avec mon échange XOR)

Array.prototype.a=function(){for(var f=[],d=0;d<this.length;d++)f[d]=this[d].a?this[d].a():this[d];return f};for(var a=[],b=0;8>b;b++)a[b]=[];for(b=2;b<process.argv.length;b++)for(var c=process.argv[b].split(""),e=0;e<c.length;e++)a[b-2][e]=parseInt(c[e],10);function h(){for(var d=l,f=0;f<d.length-2;f++)for(var g=0;g<d[f].length-2;g++){var k=d[f][g];if(k==d[f+1][g]&&k==d[f+2][g]||k==d[f][g+1]&&k==d[f][g+2])return!0}return!1}function m(){console.log("yes");process.exit()}for(b=0;b<a.length;b++)for(e=0;e<a[b].length;e++){var l=a.a();0!=b&&(l[b-1][e]^=l[b][e],l[b][e]^=l[b-1][e],l[b-1][e]^=l[b][e],h()&&m(),l=a.a());b!=a.length-1&&(l[b+1][e]^=l[b][e],l[b][e]^=l[b+1][e],l[b+1][e]^=l[b][e],h()&&m(),l=a.a());0!=e&&(l[b][e-1]^=l[b][e],l[b][e]^=l[b][e-1],l[b][e-1]^=l[b][e],h()&&m(),l=a.a());e!=a[b].length-1&&(l[b][e+1]^=l[b][e],l[b][e]^=l[b][e+1],l[b][e+1]^=l[b][e],h()&&m(),l=a.a())}console.log("no");

Notez que j'ai écrit ce tout sur mon portable et ne pas avoir le temps de le tester ou quoi que ce soit. Commentez si vous voyez des bugs, je le vérifierai moi-même plus tard.

La version lisible par l'homme avant le golf

// set it up
Array.prototype.clone = function() {
    var arr = [];
    for( var i = 0; i < this.length; i++ ) {
        if( this[i].clone ) {
             arr[i] = this[i].clone();
        } else {
             arr[i] = this[i];
        }
    }
};
var board=[];
for(var i=0;i<8;i++)board[i]=[];
for(var i=2;i<process.argv.length;i++){
    var row=process.argv[i].split("");
    for(var j=0;j<row.length;j++)board[i-2][j]=parseInt(row[j], 10);
}
// function to test
function testBoard(arr){
    for(var i=0;i<arr.length-2;i++){
        for(var j=0;j<arr[i].length-2;j++){
            var val=arr[i][j];
            if(val==arr[i+1][j] && val==arr[i+2][j])return true;
            if(val==arr[i][j+1] && val==arr[i][j+2])return true;
        }
    }
    return false;
}
// functions to exit
function yay(){console.log("yes");process.exit();}
function nay(){console.log("no");}
// super slow naive solution time
for(var i=0;i<board.length;i++){
    for(var j=0;j<board[i].length;j++){
        var newboard=board.clone();
        if(i!=0){
            newboard[i-1][j]=newboard[i-1][j]^newboard[i][j];// whoa, it's a
            newboard[i][j]=newboard[i-1][j]^newboard[i][j];  // cool algorithm
            newboard[i-1][j]=newboard[i-1][j]^newboard[i][j];// at least this 
                                                             // isn't all naive
            if(testBoard(newboard))yay();
            newboard=board.clone();
        }
        if(i!=board.length-1){
            newboard[i+1][j]=newboard[i+1][j]^newboard[i][j];
            newboard[i][j]=newboard[i+1][j]^newboard[i][j];
            newboard[i+1][j]=newboard[i+1][j]^newboard[i][j];
            if(testBoard(newboard))yay();
            newboard=board.clone();
        }
        if(j!=0){
            newboard[i][j-1]=newboard[i][j-1]^newboard[i][j];
            newboard[i][j]=newboard[i][j-1]^newboard[i][j];
            newboard[i][j-1]=newboard[i][j-1]^newboard[i][j];
            if(testBoard(newboard))yay();
            newboard=board.clone();
        }
        if(j!=board[i].length-1){
            newboard[i][j+1]=newboard[i][j+1]^newboard[i][j];
            newboard[i][j]=newboard[i][j+1]^newboard[i][j];
            newboard[i][j+1]=newboard[i][j+1]^newboard[i][j];
            if(testBoard(newboard))yay();
            newboard=board.clone();
        }
    }
}
nay();
DankMemes
la source
Hah j'ai raté le premier message de 10 minutes. J'aime un peu ça ...
DankMemes
Ah, exactement la même méthode que j'ai utilisée (code naïf mais petit!). +1 pour être beaucoup plus descriptif que moi
KSab
Je me demande s'il y a un algorithme plus efficace ...
DankMemes
2

Perl, 114 96 95 93 92 87 86 85 octets

Comprend + pour -a0p

Exécutez avec l'entrée sur STDIN:

bejeweled.pl
12314131
13224145
54762673
61716653
61341144
23453774
27645426
75575656
^D

bejeweled.pl:

#!/usr/bin/perl -a0p
$i/s%.%chop$F[$i++&7]%eg>3|/(.)((.|\H{6}|\H{9})\1|\H{7}\1.)\1/||redo;$_=$1?yes:n.o

Ceci combine une solution regex horizontale unidirectionnelle avec des rotations

Explication:

Dans cette solution, je vais tourner à plusieurs reprises et effectuer les 4 tests suivants:

/(.).\1\1/,      // 3-in-a-row horizontally after left-most shifts right
/(.)\C{9}\1\1/,  // 3-in-a-row horizontally after left-most shifts down
/(.)\C{7}\1.\1/, // 3-in-a-row horizontally after middle shifts down
/(.)\C{6}\1\1/,  // 3-in-a-row horizontally after right-most shifts down

\Cest "n'importe quel caractère" (contrairement à .cela inclut la nouvelle ligne). Sauf que cela \Cest obsolète et conduit à des avertissements, j'utilise donc \H(espace non horizontal) à la place, ce qui est assez bon pour capturer tous les chiffres et la nouvelle ligne.

Après 4 rotations, cela aura effectué les 16 tests nécessaires

-p                            Read lines from STDIN, print $_ at the end
-0                            No line ending => slurp ALL of STDIN
-a                            Split $_ into @F. Since there are no spaces
                              on the rows this means each element of @F is
                              1 row

    s%.%chop$F[$i++&7]%eg     Replace each row by the removed last column
                              This is therefore a left rotation. Very short
                              but at the cost of using @F. To make sure that
                              @F gets refilled from $_ each time I won't be
                              able to use while, until, eval or do$0 for the
                              loops but have to use redo. That costs a few
                              bytes but less than having to do my own split
$i/                      >3   The previous regex replacement always
                              returns 64 and each time through the loop $i is
                              increased by 64. So if this division reaches
                              4 all rotations have been done

/(.)((.|\H{6}|\H{9})\1|\H{7}\1.)\1/ This is the 4 regexes mentioned above
  ||redo                      Stop the loop if the regex matches or we
                              rotated 4 times
$_=$1?yes:n.o                If the regex matched $1 will be one of the
                              color digits (which cannot be 0) and this will
                              assign "yes" to $_. If the regex didn't match
                              in 4 times $1 will get its value from the last
                              succesful regex in scope which will be the one
                              from the rotation, but that one doesn't have
                              any () so $1 will be unset. So in case there
                              is no move $_ will be set to "no" (which needs
                              to be constructed because "no" is a keyword)
Ton Hospel
la source
1

Python3, 314B

import itertools as T,copy
r=[]
K=range(8)
J=[list(input())for w in K]
P=T.product
f=lambda A:["yes"for b in[A[m][n:]for m,n in P(K,K[:6])]if b[0]==b[1]==b[2]]
for i,j,x in P(K,K,[0,1]):
 t=j+1-x
 if i+x<8and t<8:B=copy.deepcopy(J);B[i][j],B[i+x][t]=B[i+x][t],B[i][j];r+=f(B)+f(list(zip(*B)))
r+=["no"]
print(r[0])

Modifiez le 8, le 5 sur la ligne 6 et les 8 sur la ligne 9 pour gérer des tailles d'entrée arbitrairement grandes; ne se soucie pas non plus de la valeur de chaque valeur, vous pouvez donc la nourrir:

absdefgh
sdkljahs
lsdfjasd
fjdhsdas
dkjhfasd
sdfhaskd
sdkfhkas
weriuwqe

et il reviendra yes.

Annotations

import itertools as T,copy 
            # itertools.product is going to save us lots of for loops
r=[]        # result
K=range(8)  # we can use range(8) everywhere, so this saves more than the usual R=range
J=[list(input())for w in K] 
            # input handling: keep everything as a length-1 string to avoid map(int,input())
P=T.product
f=lambda A:["yes"for b in[A[m][n:]for m,n in P(K,K[:6])]if b[0]==b[1]==b[2]] 
            # check the condition horiontally only. K[:6] is the same as range(5)
            # A[m][n:n+3] would be neater, but not actually needed
for i,j,x in P(K,K,[0,1]): 
            # <3 itertools.product! 3 for-loops without it.
            # NB we're only going right and downwards
 t=j+1-x
 if i+x<8and t<8: 
            # don't want out-of-bounds errors at the edges
  B=copy.deepcopy(J) 
            # preserve the reference array
  B[i][j],B[i+x][t]=B[i+x][t],B[i][j] 
            # do the switch
  r+=f(B)+f(list(zip(*B))) 
            # do the test. you could end up with lots of 'yes's in r.
            # zip(*B) takes the transpose, so that f checks the columns too
r+=["no"]   # happens to ensure that r is nonempty
print(r[0]) # only prints no if r was empty before the last line
alexander-brett
la source
1

GNU sed 255 + 2 = 257B

Je pensais que cela n'allait pas être aussi bon que python, mais c'est maintenant: - / Je n'ai pas accès à Internet aujourd'hui, donc je me suis occupé de résoudre ce problème dans sed :). Doit être appelé avec le drapeau -r, c'est-à-dire sed -rf command.sed < inputque j'ai donc ajouté 2 à mon score.

:a
$!N
s/\n/ /g
ta
:b
/^((\w)(\w\2\2|\2\w\2|\w\2\w* \w\2|\2\w* \w\w\2|\w* (\2\w* \w* \2|\w* \2\w* \2|\w\2\2|\w\2\w* \2|\2\w* \w\2|\w\2\w* \w\2))|\w((\w)(\w* \6\w\6|\6\w* \6|\w* (\6\w \w\6|\w\6\w* \6|\6\w* \6))|\w(\w)\w* \9\9))/c\yes
s/\w(\w*)/\1/g
tb
c\no

Comment ça fonctionne:

  1. Lire la grille en une seule ligne de caractères séparés par des espaces
  2. Utilisez l'expression rationnelle mère pour savoir s'il y a une correspondance dans la première colonne * - si oui, remplacez la ligne entière par «oui» (fin du programme)
  3. Supprimez le premier caractère de chaque colonne et passez à 2 si nous le faisions
  4. Si nous ne l'avons pas fait (la ligne est vide), remplacez la ligne entière par «non»
alexander-brett
la source
1

Rubis, 201 octets

J'ai été déçu de ne pas voir de solutions à ce grand défi qui n'utilisent pas d'expression régulière ou de force brute (bien que celles-ci soient excellentes), alors j'en ai écrit une. Il prend une entrée sur STDIN.

L'algorithme arithmétique au niveau du bit est dérivé de cette réponse fantastique sur Game Development Stack Exchange par @leander.

s=$<.read
$><<(?1..?9).any?{|n|a=[0]*19
s.scan(n){i=$`.size
a[i/9+1]+=2**(i%9)
a[i%9+10]+=2**(i/9)}
a.each_cons(3).any?{|x,y,z|q=y&y<<1
l=q<<1
q>>=2
y&(l<<1|q>>1)|(q|l|(y&y<<2)>>1)&(x|z)>0}}?"yes":"no"

Ruby lambda, 181 octets

Ici, c'est comme un lambda qui prend une chaîne et retourne trueou false:

->s{(?1..?9).any?{|n|a=[0]*19
s.scan(n){i=$`.size
a[i/9+1]+=2**(i%9)
a[i%9+10]+=2**(i/9)}
a.each_cons(3).any?{|x,y,z|q=y&y<<1
l=q<<1
q>>=2
y&(l<<1|q>>1)|(q|l|(y&y<<2)>>1)&(x|z)>0}}}

Voir sur repl.it: https://repl.it/ColJ/2

Non golfé & explication

->s{
  (?1..?9).any? {|n|
    a = [0] * 19

    s.scan(n) {
      i = $`.size
      a[i/9+1] += 2**(i%9)
      a[i%9+10] += 2**(i/9)
    }

    a.each_cons(3).any? {|x,y,z|
      q = y & y << 1
      l = q << 1
      q >>= 2
      y & (l << 1 | q >> 1) |
        (q | l | (y & y << 2) >> 1) &
        (x | z) > 0
    }
  }
}

Le code itère sur les chiffres "1" à "9." Chaque itération comporte deux étapes distinctes:

La première étape est la transformation du plateau, que vous pouvez voir dans le s.scan(n)bloc dans le code non golfé. Il transforme la carte en un tableau de 8 entiers, un pour chaque ligne, en traitant les chiffres correspondants comme des 1 et tous les autres comme des 0 dans une chaîne binaire. Par exemple, prenez la ligne 12231123. Dans la première itération, cela deviendra la chaîne binaire 10001100(tous les 1 deviennent - euh, reste - 1 et tous les autres chiffres deviennent 0), ce qui est le nombre décimal 140. Dans la deuxième itération, la même ligne devient 01100010(tous les 2 deviennent 2 et tous les autres chiffres deviennent 0) ou 98 décimaux.

Il effectue simultanément une deuxième transformation, qui est la même que la première mais avec la planche tournée de 90 degrés. Cela nous permet d'utiliser la même logique pour faire des correspondances horizontales que verticales. Pour plus de simplicité, il concatène les deux planches en une seule longue avec un zéro au début, au milieu (pour séparer les deux planches) et à la fin pour le rembourrage.

La deuxième étape consiste à rechercher des correspondances possibles, que vous pouvez voir dans le each_cons(3).any?bloc. Les lignes transformées (qui sont maintenant des entiers 8 bits) sont archivées (se chevauchant) en groupes de trois lignes ( x , y , z ) en utilisant une arithmétique au niveau du bit. Chaque groupe est vérifié pour voir si une correspondance peut être faite dans la rangée y , soit en décalant un morceau dans la rangée y, soit en décalant un morceau en y de x ou z . Puisqu'il y a une "rangée" nulle avant et après les rangées des planches originales et tournées, nous n'avons pas à vérifier si nous sommes sur la première ou la dernière rangée d'une planche.

Si aucune correspondance n'a été trouvée, elle continue jusqu'à l'itération suivante.

Jordan
la source