Regroupez ces cellules!

12

Ce défi est basé sur le jeu Layerz.

Étant donné, sur stdin ou comme argument de fonction, un tableau rectangulaire 2D de cellules où chaque cellule contient soit un blanc (vous pouvez choisir d'utiliser des 0 au lieu des blancs sans pénalité), un 1, un 2, un 3 ou un 4 ; trouver un moyen de le diviser en régions valides (telles que définies ci-dessous) de sorte que chaque cellule non vide soit contenue par exactement une région. Ensuite, affichez la solution trouvée dans n'importe quel format raisonnable. S'il n'y a pas de solution, soit arrêter sans produire de sortie ou sortir une seule valeur de falsey puis arrêter.

L'un des éléments suivants constitue une région valide:

  • Une seule cellule contenant un 1
  • Une cellule contenant un 2 et exactement l'un de ses voisins orthogonaux non vides
  • Une cellule contenant un 3 et exactement deux de ses voisins orthogonaux non vides
  • Une cellule contenant un 4 et exactement trois de ses voisins orthogonaux non vides

Il s'agit de , donc la réponse valide la plus courte, en octets, l'emporte.

Quelques cas de test:

1. Une question plutôt banale:

entrez la description de l'image ici

Et c'est la solution, avec chaque région dans une couleur différente:

entrez la description de l'image ici

2. Un plus intéressant

entrez la description de l'image ici

Celui-ci a plus d'une solution, mais en voici une:

entrez la description de l'image ici

3. Un plus petit, contenant des blancs, qui n'a pas de solutions (selon que vous utilisez l'un des deux pour "capturer" les trois, ou les trois pour prendre deux des deux, vous vous retrouvez avec un paire de deux non adjacents [et donc non groupables] ou un seul deux par lui-même):

entrez la description de l'image ici

Étant donné que cette grille n'a pas de solutions, votre programme doit s'arrêter sans produire aucune sortie lorsque cette grille est donnée.

4. Celui-ci (avec les 2 premiers décalés d'une cellule vers la gauche) a cependant une solution:

entrez la description de l'image ici

Solution:

entrez la description de l'image ici

(Le 2 en bas à droite est utilisé pour "capturer" le 3)

5. Parce que nous avions besoin d'un cas de test à quatre pattes:

Une solution:

SuperJedi224
la source
2
Il serait utile qu'il y ait des versions ASCII des cas de test pour que les gens n'aient pas à tous les taper, et les cas de test devraient également couvrir les 4s si ceux-ci sont des entrées valides.
Martin Ender
1
Est-ce que les voisins orthogonaux ne signifient que gauche de haut en bas, ou aussi les diagonales? si seulement à gauche en haut en bas, comment se fait-il que le 3 soit dans la même région que les deux autres 3? l'un d'eux n'est pas un voisin orthogonal.
Eyal Lev
@EyalLev Seulement gauche-droite-haut-bas. Le coin supérieur droit 3 et ses 2 voisins constituent la région.
SuperJedi224
@ SuperJedi224 en haut à droite 3 et ses deux voisins constituent une région valide, oui, mais pas ces voisins. une région ne doit-elle pas être un «ensemble fermé»? c'est-à-dire que chaque membre de la région doit être un membre valide de cette région?
Eyal Lev

Réponses:

3

Je sais que ce défi remonte à plus d'un an, mais je viens de le trouver dans "sans réponse" et il m'a semblé assez intéressant.

En supposant que le numéro de cellule "racine" est le seul significatif dans chaque région (déductible des exemples), voici ma solution de retour en arrière:

Python 3 , 355 351 349 octets

from itertools import*
def f(a):
 D=len(a[0])+1;S={D*r+c for r in range(len(a))for c in range(D-1)if a[r][c]};s=[{x,*t}for x in S for t in combinations({x-D,x-1,x+1,x+D}&S,a[x//D][x%D]-1)]
 def B(s,S,d=1):
  if{0}>S:return a
  if[]==s:return 0
  h,*t=s
  if h<=S:
   for x in h:a[x//D][x%D]=d
  return h<=S and B(t,S-h,d+1)or B(t,S,d)
 return B(s,S)

Essayez-le en ligne!

Le format d'entrée est une liste 2D d'entiers, vide comme zéro, et le format de sortie est également une liste 2D d'entiers représentant une région par nombre. Le numéro de région commence à un; zéro est réservé aux cellules vides (comme en entrée). Si l'entrée donnée est insoluble, la fonction renvoie un zéro unique (valeur falsifiée).

Par exemple, le scénario de test 5 est entré comme

[[2,3,2],
 [3,4,3],
 [0,4,0],
 [3,3,3],
 [2,3,2],
 [0,3,0]]

et la sortie est

[[1,1,1],
 [2,2,2],
 [0,2,0],
 [3,4,5],
 [3,4,5],
 [0,4,0]]

Non golfé, avec commentaires:

from itertools import*
def f(a):
 # Rows, cols, fake-cols to prevent neighbors wrap around
 R,C=len(a),len(a[0]);D=C+1
 # All valid cells represented as integers
 S={D*r+c for r in range(R) for c in range(C) if a[r][c]}
 # All valid regions rooted at each cell
 s=[{x,*t} for x in S for t in combinations({x-D,x-1,x+1,x+D}&S,a[x//D][x%D]-1)]
 # Start backtracking
 return backtrack(a,s,S,D)

# a: array to fill in the region numbers
# s: current candidates of regions
# S: current remaining cells to cover
# D: constant from f
# d: recursion depth == group number in the result
def backtrack(a,s,S,D,d=1):
 # Empty S: the board is correctly covered, return the result
 if not S:return a
 # Empty s: no more candidate regions to use, return false
 if not s:return 0
 h,*t=s
 # h is not a subset of S: h is not a valid cover, try with the rest using same depth
 if not h<=S:return backtrack(a,t,S,D,d)
 # h is a valid cover, write d to the cells in h
 for x in h:a[x//D][x%D]=d
 return backtrack(a,t,S-h,D,d+1)or backtrack(a,t,S,D,d)
 

Essayez-le en ligne!

Remarque: Il s'agit d'un cas particulier de Set Packing qui est réputé être NP-complet. Ce problème spécifique a une taille de jeu limitée (max. 4) et il existe des algorithmes d'approximation pour trouver un "bon" jeu de jeu en temps polynomial, mais ils ne garantissent pas le jeu de jeu maximum possible (ce qui est strictement requis dans ce problème).

Bubbler
la source