Réarrangement de bloc

14

Votre tâche consiste donc à prendre un bloc 3x3 où -sont les espaces vides moyens et *les espaces remplis moyens, par exemple:

-**
-*-
*-*

et réorganiser le bloc de sorte que le *s forme un X, comme ceci:

*-*
-*-
*-*

Entrée: 3x3 carrés comme ci-dessus, ils peuvent être 3 lignes, un tableau ou comme vous le souhaitez.

Sortie: le plus petit nombre de mouvements à réorganiser en X. Chaque mouvement retourne 2 caractères qui se touchent et sont horizontaux l'un de l'autre, verticaux l'un de l'autre ou diagonaux l'un de l'autre. Si ce n'est pas possible, renvoyez toute sortie impossible, par exemple 999ou -4242. 5est le plus petit de ces nombres.

Cas de test:

1) Sortie: 1

-**
-*-
*-*

2) Sortie: -1

-*-
-*-
*-*

3) Sortie: 3

---
-**
***

4) Sortie: 0

*-*
-*-
*-*

Vous pouvez remplacer les caractères vides et non vierges mais assurez-vous d'inclure lequel est lequel dans votre message

Code Golf

N'oubliez pas que c'est le golf de code le code le plus court gagne!

Noah Cristino
la source
1
En retournant 2 caractères, vouliez-vous dire retourner de l'espace vers *et vice versa, ou les échanger?
user202729
Et s'il y en a plus de cinq *? Pouvez-vous ajouter des cas de test supplémentaires?
Stewie Griffin
@ user202729 par exemple abc serait acb si vous inversiez les 2 derniers caractères.
Noah Cristino
@StewieGriffin "si ce n'est pas possible, renvoyer un -1" plus de 5 *ou moins de 5 rend impossible.
Noah Cristino
6
Pouvons-nous utiliser autre chose que -1? Par exemple 5(impossible autrement), ou lancer une erreur?
Jonathan Allan

Réponses:

12

Python 3 , 104 78 octets

lambda n:-(sum(n)!=5)or sum(n[1::2])+n[4]*(max(n,n[6:],n[::3],n[2::3])>=[1]*3)

Essayez-le en ligne!

Edit: appliqué les suggestions de @Jonathan Allan et @ xnor pour réduire considérablement le nombre d'octets.

L'entrée est une liste de chaînes de longueur 9 avec des zéros et des uns, les uns étant les *s.

Voici quelques observations:

  • Nous n'avons jamais besoin de déplacer les étoiles déjà sur les bonnes cellules. Toute étoile mal placée a 5 cellules environnantes qui ne peuvent pas être bloquées à la fois (sinon la réponse est déjà -1).
  • Le coût de chaque étoile mal placée est de 1 ou 2, et il est de 2 seulement si elle est entourée de trois étoiles correctement placées.
  • Le coût de chaque étoile mal placée est indépendant les uns des autres.

Par conséquent, nous testons d'abord si la chaîne en a cinq, puis comptons ces choses:

  • Le nombre d'étoiles mal placées (= celles aux indices impairs)
  • Le nombre d'étoiles égarées de coût 2 (= cellules à 0124, 0346, 2458, 4678étant tous les)
    • Factor out out n[4]one, puis testez chaque plage d'extraction '111'.
    • Étant donné qu'une telle étoile est au plus une, nous pouvons utiliser en toute sécurité maxau lieu de sum.
Bubbler
la source
Économisez 17 octets en acceptant une liste au lieu d'une chaîne (en remplaçant counts par sums et '111'par [1]*3) TIO (j'ai essayé d'être intelligent avec une n[i::j]>=[1]*3boucle mais je n'ai pas trouvé plus court).
Jonathan Allan
Puisqu'il ne peut y avoir qu'une seule étoile coût-2, il semble que vous puissiez le faire max(n,n[6:],n[::3],n[2::3])>='1'*3.
xnor
Il y a d'autres arrangements qui ont une étoile au coût de 2. Je pense que [0,1,1,1,1,0,1,0,0] devrait renvoyer 3 au lieu de 2.
RootTwo
De plus, [1,1,1,1,0,0,1,0,0] devrait être 3 au lieu de 2.
RootTwo
De plus, [1,1,1,1,0,0,1,0,0] devrait être 3 au lieu de 2.
RootTwo
4

Gelée , 26 octets

5ḶḤd3ạŒ!Ṁ€€ḅ1Ṃ
T’d3Ç-L=5Ɗ?

Essayez-le en ligne!


Prenez une liste plate en entrée.

Dommage que Jelly n'ait pas d '"indices véridiques multidimensionnels" ... T€ṭ€"JẎfonctionne aussi mais prend 1 octet de plus.


Algorithme: Il y a 5 positions de bloc actuelles et 5 cibles (destinations), l'algorithme essaie chacun des 5! correspondant et afficher la somme minimale de la distance [source, destination] Chebyshev.

user202729
la source
Vous pouvez prendre une liste plate ("comme vous voulez") ... peut-être pouvez-vous même prendre des indices basés sur 0 et en avoir 24?
Jonathan Allan
4

Haskell , 176 132 126 126 104 octets

w=0:1:w
m a|sum a/=5=5|1>0=sum$[a!!4|3<-sum.map(a!!)<$>[[0,1,2],[0,3,6],[2,5,8],[6,7,8]]]++zipWith(*)a w

Essayez-le en ligne!


Prend une liste d'entiers avec 1 comme caractère non vide. Additionne le nombre de carrés indexés non nuls, puis ajoute 1 si l'un des motifs de déplacement double est trouvé (carré central et colonne / ligne de bord complètement remplis). La dernière partie est un peu inutile, je pense, pourrait probablement être beaucoup améliorée par rapport à cette méthode de force brute. Renvoie 5 (une sortie impossible) sur une entrée impossible.

aoemica
la source
2
Quelques conseils: le lengthtest peut être raccourci sum[1|1<-a]. Fonction svers (1-e,n+sum[1|b>e])laquelle vous pouvez vous connecter pour enregistrer un autre octet. Vous pouvez utiliser la otherwisegarde dans mla sauvegarde deux (). Enfin, &&au niveau supérieur dans un garde peut être remplacé par ,. ...
nimi
2
Vous pouvez enregistrer un autre octet en utilisant une sumcompréhension sur une liste pour convertir un booléen en int. Essayez-le en ligne!
Post Rock Garf Hunter
2
En fait, vous pouvez économiser quelques octets, car une fois que les protections de modèle ont disparu, vous pouvez simplement déplacer le tout vers le haut m. Essayez-le en ligne!
Post Rock Garf Hunter
2
De plus, comme chaque élément non-1 de amust be 0ne peut pas être utilisé à la sum aplace de sum[1|1<-a]? Essayez-le en ligne!
Post Rock Garf Hunter
1
Je viens de réaliser qu'il ne peut y avoir plus d'un côté avec tous les 1s à moins que le centre ne soit 0, vous pouvez faire à la 3<-place de elem 3$. Vous pouvez également utiliser à la sum.map(a!!)place de sum<$>map(a!!).
Post Rock Garf Hunter
3

Python 2 , 194 192 octets

from itertools import*
f=lambda l,k=0:-(sum(l)!=5)or[1,0]*4!=l[:-1]and k<4and-~min(f(l[:a]+[l[b]]+l[a+1:b]+[l[a]]+l[b+1:],k+1)for a,b in combinations(range(9),2)if max(b/3-a/3,abs(a%3-b%3))<2)

Essayez-le en ligne!

ovs
la source
1
Ne fonctionne pas avec [0,1,0,1,0,1,1,1,0](attendu: 4, réel: 13).
Bubbler
@Bubbler l'a corrigé
ovs
3

JavaScript (ES6), 123 octets

Prend l'entrée comme un entier de 9 bits. Résout le casse-tête en appliquant naïvement les règles, ce qui s'est avéré ne pas être l'approche la plus courte.

f=(n,k=b=-1)=>n^341?k>2?b:[3,6,9,10,17,18,20,34,36].map(m=>[1,8,8].map(M=>(x=n&(m*=M))&-x^x||f(n^m,k+1)))|b:!~b|k<b?b=k+1:b

Essayez-le en ligne!

Commenté

f = (                           // f = recursive function taking:
  n,                            //   n = input
  k =                           //   k = number of moves, initialized to -1
  b = -1                        //   b = best result so far, initialized to -1
) =>                            //
  n ^ 341 ?                     // if n does not match the target pattern:
    k > 2 ?                     //   if we've already done more than 3 moves:
      b                         //     we're not going to find a solution -> abort
    :                           //   else:
      [3,6,9,10,17,18,20,34,36] //     for each swap bitmask m
      .map(m =>                 //     and
      [1,8,8]                   //     for each multiplier M:
      .map(M =>                 //       apply the multiplier to m and
        (x = n & (m *= M))      //       apply the final bitmask to n -> this gives x
        & -x                    //       isolate the least significant bit of x
        ^ x ||                  //       if it's the only bit set,
        f(n ^ m, k + 1)         //       then swap the bits and make a recursive call
      )) | b                    //     end of both map() loops; return b
  :                             // else:
    !~b | k < b ? b = k + 1 : b //   this is a solution in k+1 moves: update b

NB : Ce code effectue des mouvements illégaux au-delà du haut du plateau lorsque m est multiplié par 64. Mais ils sont simplement ignorés, car ils ne peuvent pas conduire à une solution plus courte que la meilleure solution légale.

Vous trouverez ci-dessous les 9 masques de bit d'échange de base et le motif cible. Le coin supérieur gauche est le bit le plus significatif.

000  000  001  001  010  010  010  100  100     101
011  110  001  010  001  010  100  010  100     010 (341)
(3)  (6)  (9)  (10) (17) (18) (20) (34) (36)    101
Arnauld
la source
Pouvez-vous lier un hexdump pour le tester? De plus, je ne savais pas que des entiers 9 bits étaient possibles dans JS
Stan Strum
@StanStrum Mise à jour vers une version plus courte avec un encodage plus simple. (Et oui: JS prend en charge les opérations au niveau du bit jusqu'à 32 bits.)
Arnauld
2

Gelée , 26 octets

“ċȤ‘ḤB;U$=a¥;Ḋm2ƊẠ€SɓSn5Nȯ

Essayez-le en ligne!

Un lien monadique.

Comment?

Inspiré par la réponse Python de Bubbler ; golfé pour convenir à Jelly ...

“ċȤ‘ḤB;U$=a¥;Ḋm2ƊẠ€SɓSn5Nȯ - Link: length 9 list of ones & zeros, X
“ċȤ‘                       - list of code-page indices     = [232,154]
    Ḥ                      - double                        = [464,308]
     B                     - to binary     = [[1,1,1,0,1,0,0,0,0],[1,0,0,1,1,0,1,0,0]]
        $                  - last two links as a monad:
       U                   -   upend       = [[0,0,0,0,1,0,1,1,1],[0,0,1,0,1,1,0,0,1]]
      ;                    -   concatenate = [[1,1,1,0,1,0,0,0,0],[1,0,0,1,1,0,1,0,0],[0,0,0,0,1,0,1,1,1],[0,0,1,0,1,1,0,0,1]]
           ¥               - last two links as a dyad:
          a                -   logical AND (vectorises)
         =                 -   equal? (vectorises)
                Ɗ          - last three links as a monad:
             Ḋ             -   dequeue X (remove leftmost element)
               2           -   literal two
              m            -   modulo slice (keeps the "edge-elements") 
            ;              - concatenate
                 Ạ€        - all? for €ach (edge-elements: no-op
                           -                else: 1 for any cost-2 element 0 otherwise)
                   S       - sum
                    ɓ      - new dyadic chain ^that on the right; X on the left
                     S     - sum X
                       5   - literal five
                      n    - not equal?
                        N  - negate (-1 if not exactly 5 1s, 0 otherwise)
                         ȯ - logical OR with right
Jonathan Allan
la source
2

JavaScript, 85 octets

s=>/^0*(10*){5}$/.test(s)*s.match(/(?=1.(..)*$|^1(..)?11.1|1.11(..)?1$)|$/g).length-1

Ceci est un port regex de la réponse de Bubbler .

Saisissez une chaîne de 0/1.

tsh
la source
2

Stax , 23 22 octets

Ç╙╤Ü┤└åVτ┐├Y-²▼░█∩¡3ëâ

Exécuter et déboguer

Ce programme prend un tableau de [0, 1]comme entrée et retourne un nombre entier de mouvements, ou une chaîne vide si aucune solution n'est possible.

Considérez ces indices pour la grille

0 1 2
3 4 5
6 7 8
  • S'il n'y a pas exactement 5 1s dans l'entrée, alors il n'y a pas de solution, donc nous ne produisons aucune sortie.
  • Les centres de chaque côté sont les positions incorrectes. Ce sont les indices 1, 3, 5 et 7. La somme de la distance pour chacun 1de ces positions produira le résultat final.
  • Pour chacun 1dans une position incorrecte, sa distance est soit 1 ou 2. Ce sera 2 ssi il est entouré d'autres 1s. Par exemple, s'il y a 1s aux indices [0, 1, 2, 4], alors la distance pour le mauvais 1est 2.
  • Dans cet esprit, considérez ce pseudo-code pour obtenir la distance contribuée au résultat par l'index 1.

    1. Lire 4 bits à partir des indices [1, 0, 2, 4]. Cela place la position incorrecte dans la position la plus importante.
    2. Convertissez ces bits en un nombre bde 0 à 15.
    3. Lorsque 0 <= b <= 7la distance est 0. Lorsque 8 <= b <= 14la distance est 1. Lorsque b == 15la distance est 2. Ceci peut être calculé en utilisant la division entière par b * 2 / 15.

Ainsi, la distance totale peut être calculée en répétant ce processus 4 fois et en faisant tourner la grille entre les deux.

1#5=4*  if the number of 1s is 5, then 4, else 0
D       repeat the rest of the program that many times
  x     push the value in the x register, which is initially the input
  3/    split into 3 rows
  rM    rotate 90 degrees
  $X    flatten back into single array, and save the "rotated" array in the X register
  A|2E  get the digits of 2^10 i.e. [1,0,2,4]
  @     read the bits from the current rotation at indices [1,0,2,4]
  :b    convert bits to integer
  H15/  double, then divide by 2
  +     add to running total

Exécutez celui-ci

récursif
la source
Vérifiez l'édition, toute valeur impossible est acceptée, pas seulement -1 si cela vous aide
Noah Cristino
Oui. Cela a permis d'économiser 2 octets.
récursif
1

Excel, 86 81 octets

=SUM(B1,A2,B3,C2)+B2*(AND(A1:A3)+AND(A1:C1)+AND(C1:C3)+AND(A3:C3))/(SUM(A1:C3)=5)

Ancien: lorsque la sortie «impossible» était-1

=IF(SUM(A1:C3)=5,SUM(B1,A2,B3,C2)+B2*(AND(A1:A3)+AND(A1:C1)+AND(C1:C3)+AND(A3:C3)),-1)

Utilise 1pour rempli et 0pour vide, entrée dans la plage A1:C3. Possibilité de jouer au golf plus loin si nous pouvons retourner des valeurs autres que -1"impossible". Retourne une #DIV/0!erreur sur les grilles impossibles

Fonctionne sur la même logique que la réponse Python de Bubbler .

Chronocide
la source
Vérifiez l'édition, toute valeur impossible est acceptée, pas seulement -1
Noah Cristino