Dividir una cuadrícula en una cuadrícula

22

Introducción

Hay un pequeño pueblo con pocas casas y campos vacíos. Los burócratas locales quieren dividir el pueblo en lotes para que cada lote contenga exactamente una casa, y los bordes de los lotes formen una bonita cuadrícula en línea recta. Su tarea es determinar si esto es posible.

La tarea

Su entrada es una matriz rectangular 2D de bits; 1 representa una casa y 0 un campo vacío. Su tamaño será de al menos 1 × 1 , y contendrá al menos uno 1. Puede tomar la entrada en cualquier formato razonable (lista anidada de enteros, lista de cadenas, cadena multilínea, etc.).

Su programa determinará si la matriz se puede dividir en celdas de cuadrícula utilizando líneas horizontales y verticales rectas para que cada celda de cuadrícula contenga exactamente uno 1. Las celdas de cuadrícula pueden tener diferentes tamaños y formas, aunque siempre serán rectangulares. Las líneas deben correr desde un borde de la matriz hasta el borde opuesto.

Por ejemplo, la siguiente es una división válida de una matriz:

00|0010|01|1
01|0000|00|0
--+----+--+-
00|0000|00|1
01|0010|01|0
--+----+--+-
01|1000|10|1

mientras que la siguiente división no es válida, ya que hay celdas de cuadrícula sin 1 o más de un 1:

00|0010|01|1
--+----+--+-
01|0000|00|0
00|0000|00|1
01|0010|01|0
--+----+--+-
00|1000|10|1

Si existe una división válida, deberá generar un valor verdadero y, de lo contrario, un valor falso.

Reglas y puntaje

Puede escribir un programa completo o una función. El conteo de bytes más bajo gana.

Casos de prueba

[[1]] -> True
[[0,1],[1,0]] -> True
[[1,1],[1,0]] -> False
[[1,0,1],[0,1,0]] -> True
[[1,0],[0,1],[0,1]] -> True
[[1,0,0],[0,0,1],[0,1,1]] -> True
[[1,1,1],[1,1,1],[1,1,1]] -> True
[[1,0,1],[0,1,0],[1,0,0]] -> True
[[1,0,0],[1,0,0],[0,1,1]] -> False
[[0,0,0,0,1],[1,0,0,1,0],[0,0,0,1,0]] -> False
[[0,0,1,0,1],[0,0,0,1,0],[0,0,0,0,0]] -> True
[[1,1,0,0,0],[0,0,0,0,0],[1,0,1,0,0]] -> True
[[1,1,0,1,1],[0,1,0,1,1],[1,0,0,0,0]] -> True
[[0,0,0,0,0,0,0],[0,1,1,1,0,1,0],[0,1,0,0,1,0,0],[0,0,0,0,0,0,1],[0,0,1,0,0,0,1],[1,1,0,1,1,0,0]] -> False
[[1,1,0,0,0,0,0],[1,0,1,1,0,1,0],[0,0,0,0,1,0,0],[0,1,0,1,1,0,0],[1,0,0,0,1,1,0],[0,0,0,0,0,1,0]] -> False
[[0,1,0,1,1,1,0],[0,0,0,0,1,0,0],[0,0,0,0,0,0,0],[1,0,0,1,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,1]] -> True
[[0,1,0,0,1,0,1],[1,0,0,0,1,0,1],[0,0,1,0,1,0,1],[1,0,0,0,1,1,0],[0,0,0,1,1,1,0],[0,1,0,0,1,0,1]] -> True
[[0,1,0,0,1,0,0,1,0],[0,0,0,0,1,1,0,1,0],[1,1,0,0,1,0,0,0,0],[0,0,1,0,1,0,1,0,0],[0,0,1,0,1,0,1,0,0],[0,1,0,0,0,1,0,0,1],[0,1,0,0,0,0,1,0,0]] -> False
[[1,0,1,0,0,1,1,0,1],[0,1,1,0,0,1,1,0,1],[1,0,0,0,0,1,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,1,0,0,0,0,1,1],[0,1,1,0,1,0,1,0,1],[1,0,1,0,0,1,1,0,1]] -> True
Zgarb
fuente
puede [[0,0,1,0,1], [1,0,0,1,0], [0,0,0,1,0]] dividirse en: 3X1, 2X1, 3X2, 2X1, ¿Rectángulos 2X1 de esta manera o no? 001 | 01 --- + - 100 | 10 + - 000 | 10
officialaimm
44
@officialaimm No, eso no es válido. Las líneas de la cuadrícula deben ejecutarse desde un lado de la matriz hasta el otro lado.
Zgarb
Caso de prueba propuesto: [[1, 0, 1], [0, 1, 0], [1, 0, 0]]esa era la única matriz 3x3 por la que fallaba mi nuevo enfoque.
Dennis
@ Dennis Gracias, agregó.
Zgarb

Respuestas:

7

Pyth, 30 29 26 24 23 bytes

sm.Asmmq1ssbCkds./MC./M

Pruébalo en línea.

Estoy seguro de que esto se acortará. Esto es O (2 mn ) , donde m y n son la anchura y la altura de la matriz, pero completa los dos últimos casos de prueba en 45 segundos en mi portátil en la batería (i5-5200U con rendimiento limitado).

Emite el número de soluciones.

Explicación

Es muy divertido trabajar con matrices de cinco dimensiones. </sarcasm> Se supone que no debes entender cómo funciona esto incluso con la explicación.

                    ./M    Find all partitions of each row. Now we have a list of rows,
                           each containing the ways to split the row, each containing
                           the parts of the split (3D).
                   C       Transpose. Now we have a list of ways to split the columns,
                           each containing the rows, each containing the parts of the
                           row (3D).
                ./M        Find all partitions of each row list. Now we have a list of
                           ways to split the columns, each containing the ways to split
                           the rows, each containing the bunch of rows, each containing 
                           the rows in the bunch, each containing the parts of the row
                           (6D).
               s           Combine the ways to split rows & columns into one array (5D).
 m            d            Do the following for each way to split rows & columns (4D):
     m       k                 Do the following for each bunch of rows (3D):
            C                      Transpose the array. We now have a list of column
                                   groups, each containing the row parts (3D).
      m    b                       Do the following for each column group (2D):
          s                            Combine the row parts in the column group. We now
                                       have the list of cells in this row/column group
                                       (1D).
         s                             Sum the cells.
       q1                              Check if the sum is one.
                                   We now have the list of booleans that tell if each
                                   row/column group is valid (1D).
                               We now have the 2D list of booleans that tell if each
                               row/column group in each bunch of rows is valid. (2D)
    s                          Combine the 2D list of booleans to 1D.
  .A                           Check if all values are truthy; if the split is valid.
                           We now have the validity of each split.
s                          Sum the list to get the number of valid solutions.
PurkkaKoodari
fuente
2

Haskell , 116 bytes

import Data.List
m(a:b)=[a:e|e<-m b]++[zipWith(+)a d:e|d:e<-m b];m e=[e]
d=(any$any$all$all(==1)).map(m.transpose).m

Pruébalo en línea!

Roman Czyborra
fuente
1
Esto no se compila. Elimine su respuesta hasta que se solucione. También hay mucho potencial de golf, por ejemplo. renombrando mergerowsa m.
Laikoni el
Estaba planeando quedarme sin competencia debido a la brevedad de Pyth difícil de vencer y gracias a ti @Laikoni por ver que probablemente estropeé mis llaves de sangría.
Roman Czyborra
2
Esto da incorrectamente Falso en [[1,0],[0,1],[1,0]]. El problema es que un colapso codicioso puede obstaculizar un colapso posterior mejor.
xnor
De hecho, mi [[1,1],[1,0]]colapso obstruye falsamente la [[1],[1],[1]]solución. Déjame dormir sobre esto o ¿debería eliminarlo?
Roman Czyborra
1

Jalea , 20 bytes

ŒṖS€€ỊȦ$ÐfZ€µ⁺€Ȧ€€FS

Esta sigue siendo una solución de fuerza bruta, pero es bastante más rápida que mi otra respuesta, que no puede hacer frente a los dos últimos casos de prueba en TIO, y maneja todos los casos de prueba en ~ 4 segundos.

Pruébalo en línea!

Cómo funciona

ŒṖS€€ỊȦ$ÐfZ€µ⁺€Ȧ€€FS  Main link. Argument: M (matrix, array of rows)

ŒṖ                    Compute all partitions, i.e., all groupings of M's rows.
  S€€                 Map sum over all individual groupings, collapsing the grouped
                      rows into a single row.
        Ðf            Filter; keep only those partially collapsed matrices for
                      which the link to the left returns a truthy value.
       $                Group the two links to the left into a monadic chain.
     Ị                    Insignificant; map 0 and 1 to 1, greater integers to 0.
      Ȧ                   All; return 1 iff the matrix contains no zeroes.
          Z€          Zip/transpose all kept matrices,
            µ         Combine all links to the left into a monadic chain.
             ⁺€       Duplicate the chain and map it over the individual results
                      from the first call. We now have all possible combinations
                      of row and column groupings (represented by the corresponding
                      matrices of collapsed rows and columns) that do not have a
                      2 anywhere. However, they still may contain zeroes.
               Ȧ€€    Map the all atom over the matrices, returning 1 only for
                      matrices that consist entirely of ones.
                  FS  Flatten and sum, counting the number of valid divisions.
Dennis
fuente