Agrupe essas células!


12

Este desafio é baseado no jogo Layerz.

Dado, no stdin ou como argumento de função, uma matriz retangular de células 2D em que cada célula contém um espaço em branco (você pode optar por usar 0s em vez de espaços em branco sem penalidade), 1, 2, 3 ou 4 ; encontre uma maneira de dividi-lo em regiões válidas (conforme definido abaixo), de modo que cada célula não em branco esteja contida em exatamente uma região. Em seguida, imprima a solução encontrada em qualquer formato razoável. Se não houver solução, pare sem produzir saída ou produza um único valor de falsey e pare.

Qualquer um dos seguintes constitui uma região válida:

  • Uma única célula contendo 1
  • Uma célula contendo um 2 e exatamente um de seus vizinhos ortogonais não vazios
  • Uma célula contendo um 3 e exatamente dois de seus vizinhos ortogonais não vazios
  • Uma célula contendo 4 e exatamente três de seus vizinhos ortogonais não vazios

Isso é , então a resposta mais curta e válida, em bytes, vence.

Alguns casos de teste:

1. Um tanto trivial:

insira a descrição da imagem aqui

E esta é a solução, com cada região em uma cor diferente:

insira a descrição da imagem aqui

2. Mais interessante

insira a descrição da imagem aqui

Este tem mais de uma solução, mas aqui está um deles:

insira a descrição da imagem aqui

3. Um menor, contendo espaços em branco, que não possui soluções (dependendo de você usar um dos dois para "capturar" os três ou os três para capturar dois dos dois, você fica com um par de dois não adjacentes [e, portanto, não agrupáveis] ou um único dois por si só):

insira a descrição da imagem aqui

Como essa grade não tem soluções, seu programa deve parar sem produzir nenhuma saída quando receber essa grade.

4. Esta (com as duas principais deslocadas uma célula para a esquerda) possui uma solução:

insira a descrição da imagem aqui

Solução:

insira a descrição da imagem aqui

(O canto inferior direito 2 é usado para "capturar" os 3)

5. Porque precisávamos de um caso de teste com alguns quatro:

Uma solução:


2
Seria útil se houvesse versões ASCII dos casos de teste para que as pessoas não precisem digitá-las todas, e os casos de teste também devem cobrir 4s se essas são entradas válidas.
Martin Ender

1
vizinhos ortogonais significa apenas esquerda para cima ou para baixo, ou também as diagonais? se apenas deixada de cima para baixo, como os 3 estão na mesma região que os outros 3? um deles não é um vizinho ortogonal.
precisa

@EyalLev Apenas esquerda-direita-cima-baixo. O canto superior direito 3 e seus 2 vizinhos constituem a região.
SuperJedi224

@ SuperJedi224 no canto superior direito 3 e seus dois vizinhos constituem uma região válida, sim, mas esses vizinhos não. uma região não precisa ser um "conjunto fechado"? ou seja, cada membro da região deve ser um membro válido dessa região?
Eyal Lev

Respostas:


3

Eu sei que esse desafio tem mais de um ano, mas eu o encontrei em "sem resposta" e me pareceu bastante interessante.

Supondo que o número da célula "raiz" seja o único significativo em cada região (dedutível nos exemplos), aqui está minha solução de retorno:

Python 3 , 355 351 349 bytes

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)

Experimente online!

O formato de entrada é uma lista 2D de números inteiros, em branco como zero, e o formato de saída também é uma lista 2D de números inteiros representando uma região por número. O número da região começa em um; zero é reservado para células em branco (como na entrada). Se a entrada fornecida for insolúvel, a função retornará zero único (valor falso).

Por exemplo, o caso de teste 5 é inserido como

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

e a saída é

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

Ungolfed, com comentários:

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)
 

Experimente online!

Nota: Este é um caso especial de Set Packing que é conhecido por ser NP-complete. Esse problema específico tem tamanho de conjunto limitado (máx. 4) e existem algoritmos de aproximação para encontrar o conjunto "bom" de conjuntos em tempo polinomial, mas eles não garantem o conjunto máximo possível de conjuntos (o que é estritamente necessário neste problema).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.