Crack le coffre-fort!

10

Inspiré par /puzzling/24334/to-catch-a-thief

Vous obtenez une grille npar n( nelle-même est une entrée facultative) remplie de 0s et 1s (ou tout autre caractère de votre choix). Votre objectif est de rendre chaque cellule identique (soit 0ou 1). Vous pouvez effectuer une série de mouvements comme défini ci-dessous (notez la différence avec le lien Puzzling SE):

  • Sélectionnez une cellule.
  • Chaque cellule de la même ligne et colonne (à l'exception de la cellule elle-même) est transformée en son contraire. 0vers 1et 1vers 0.

Générez le nombre minimum de mouvements requis pour terminer la tâche. Si insoluble, sortez tout sauf un entier non négatif. Le code le plus court gagne.

Exemples de données

1 0 0
0 0 0
0 0 0

-1

1 1 1
1 1 1
1 1 1

0

1 0 1
0 1 0
1 0 1

1

1 1 1 1
0 0 0 0
0 0 0 0
1 1 1 1

2

0 1 0 1
1 0 1 0
1 0 1 0
0 1 0 1

2

ghosts_in_the_code
la source
3
Que faire si le puzzle est insoluble? Par exemple 1000(réarrangé en carré, peu importe comment).
orlp
2
En relation.
Martin Ender
@orlp Toute sortie qui n'est pas un nombre fera l'affaire.
ghosts_in_the_code
Avons-nous besoin d'analyser l'entrée ou peut-il s'agir d'un type de données de tableau déjà rempli?
coredump
1
Quelle est la solution au premier cas de test? Je n'obtiens aucune solution.
cardboard_box

Réponses:

4

Matlab 171 octets

L'entrée doit être une matrice 2d, vous pouvez donc l'appeler comme c([1,1,1,1;0,0,0,0;0,0,0,0;1,1,1,1])(les points-virgules commencent une nouvelle ligne). Cette fonction renforce simplement tous les mouvements possibles, nous obtenons donc un runtime de O(2^(n^2)).

Comment c'est fait

Cela se fait en choisissant toutes les façons possibles de remplir une autre matrice de la même taille avec des uns et zéro, c'est essentiellement compter en binaire où chaque entrée de la matrice représente une certaine puissance de 2.

Ensuite, nous effectuons les déplacements sur les cellules qui sont 1, cela se fait par la somme (mod 2) de deux convolutions bidimensionnelles avec un vecteur de celles de taille 1xn et nx1.

Enfin, nous décidons si ces mouvements ont réellement produit le résultat souhaité, en calculant l'écart type sur toutes les entrées. L'écart type n'est de zéro que si toutes les entrées sont identiques. Et chaque fois que nous avons réellement trouvé le résultat souhaité, nous le comparons avec le nombre de mouvements des solutions précédentes. La fonction reviendra infsi le problème donné n'est pas résolu.

Math?

Il est en fait intéressant de noter que tous ces mouvements génèrent ensemble un groupe abélien! Si quelqu'un parvient à calsifier ces groupes, faites-le moi savoir.

Version golfée:

function M=c(a);n=numel(a);p=a;M=inf;o=ones(1,n);for k=0:2^n-1;p(:)=dec2bin(k,n)-'0';b=mod(conv2(p,o,'s')+conv2(p,o','s'),2);m=sum(p(:));if ~std(b(:)-a(:))&m<M;M=m;end;end

Version complète (avec la sortie des mouvements réels.)

function M = c(a)
n=numel(a);
p=a;
M=inf;                                               %current minimum of number of moves
o=ones(1,n);
for k=0:2^n-1;
    p(:) = dec2bin(k,n)-'0';                         %logical array with 1 where we perform moves
    b=mod(conv2(p,o,'same')+conv2(p,o','same'),2);   %perform the actual moves
    m=sum(p(:));                                     %number of moves;
    if ~std(b(:)-a(:))&m<M                           %check if the result of the moves is valid, and better
        M=m;
        disp('found new minimum:')
        disp(M)                                      %display number of moves of the new best solution (not in the golfed version)
        disp(p)                                      %display the moves of the new best solution                               (not in the golfed version)
    end
end
flawr
la source
1

Perl 5, 498 octets

Cela accepte «n» et le résultat souhaité, et génère le nombre, ou «X» si aucun.

Par exemple:

perl ./crack.golf.pl 3 000111111

donne 2. Cela ne fonctionnera que lorsque n ^ 2 <= 64, donc n <= 8. Bien qu'il soit assez lent même avec n aussi faible que 5. Il construit un tableau ^ 3 bits et trie un tableau 2 ^ (n ^ 2) au préalable, car pourquoi pas ?

J'ai gaspillé quelques sauts de ligne ici pour plus de lisibilité :

$n=shift;$y=shift;$p=$n*$n;@m=(0..$n-1);@q=(0..$p-1);@v=(0..2**$p-1);@d=map{0}(@q);@b=map{$r=$_;map{$c=$_;$d[$r*$n+$_]^=1 for(@m);$d[$_*$n+$c]^=1 for(@m);$j=0;$k=1;
map{$j|=$k*$d[$_];$k<<=1;}@q;@d=map{0}(@q);$j;}@m}@m;for$k(sort{$a->[0]<=>$b->[0]}map{$z=0;map{$z+=$_}split(//,sprintf"%b",$_);[$z,$_]}@v){$l=sprintf"%0${p}b",$k->[1];
@m=map{$_}split(//,$l);$s=0;for(@q){$s^=$b[$_]if$m[$_];}$z=0;map{$z+=$_}split(//,sprintf"%b",$_);if($y eq sprintf"%0${p}b",$s){print"$k->[0]\n";exit 0;}}print"X\n";
Dale Johnson
la source