Dividir uma grade em uma grade

22

Introdução

Há uma pequena vila com nada além de poucas casas e campos vazios. Os burocratas locais querem dividir a vila em lotes, de modo que cada lote contenha exatamente uma casa, e as bordas dos lotes formam uma ótima grade linear. Sua tarefa é determinar se isso é possível.

A tarefa

Sua entrada é uma matriz 2D retangular de bits; 1 representa uma casa e 0 um campo vazio. Seu tamanho será de pelo menos 1 × 1 e conterá pelo menos um 1. Você pode receber a entrada em qualquer formato razoável (lista aninhada de números inteiros, lista de cadeias, cadeia multilinha etc.).

Seu programa deve determinar se a matriz pode ser dividida em células da grade usando linhas horizontais e verticais retas, de modo que cada célula da grade contenha exatamente um 1. As células da grade podem ter tamanhos e formatos diferentes, embora sempre sejam retangulares. As linhas devem ser executadas de uma borda da matriz até a borda oposta.

Por exemplo, a seguir é uma divisão válida de uma matriz:

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

considerando que a divisão a seguir não é válida, pois existem células de grade sem 1s ou mais de 1:

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

Se existir uma divisão válida, você deve gerar um valor verdadeiro e, caso contrário, um valor falso.

Regras e pontuação

Você pode escrever um programa completo ou uma função. A menor contagem de bytes vence.

Casos de teste

[[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
fonte
pode [[0,0,1,0,1], [1,0,0,1,0], [0,0,0,1,0]] ser dividido em: 3X1, 2X1, 3X2, 2X1, Retângulos 2X1 dessa maneira ou não? 001 | 01 --- + - 100 | 10 + - 000 | 10
officialaimm
4
@officialaimm Não, isso não é válido. As linhas de grade devem ser executadas de um lado da matriz até o outro lado.
Zgarb 23/01
Caso de teste proposto: [[1, 0, 1], [0, 1, 0], [1, 0, 0]]Essa foi a única matriz 3x3 em que minha nova abordagem estava falhando.
Dennis
@ Dennis Obrigado, acrescentou.
Zgarb

Respostas:

7

Pitão, 30 29 26 24 23 bytes

sm.Asmmq1ssbCkds./MC./M

Experimente online.

Tenho certeza que isso ficará mais curto. Este é O (2 min ) , onde m e n são a largura e a altura da matriz, mas conclui os dois últimos casos de teste em 45 segundos no meu laptop com bateria (i5-5200U com desempenho limitado).

Produz o número de soluções.

Explicação

É realmente divertido trabalhar com matrizes tridimensionais. </sarcasm> Você não deveria entender como isso funciona, mesmo com a explicação.

                    ./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
fonte
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

Experimente online!

Roman Czyborra
fonte
1
Isso não compila. Exclua sua resposta até que seja corrigida. Há também muito potencial de golfe, por exemplo. renomeando mergerowspara m.
Laikoni 23/01
Eu estava planejando ficar sem concorrência devido à brevidade difícil de vencer de Pyth e agradeço a @Laikoni por detectar que eu provavelmente estraguei minhas chaves de indentação.
Roman Czyborra
2
Isso incorretamente fornece Falso [[1,0],[0,1],[1,0]]. O problema é que um colapso ganancioso pode atrapalhar um colapso melhor posterior.
Xnor
De fato, meu [[1,1],[1,0]]colapso obstrui falsamente a [[1],[1],[1]]solução. Deixe-me dormir sobre isso ou devo excluir?
Roman Czyborra
1

Gelatina , 20 bytes

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

Essa ainda é uma solução de força bruta, mas é um pouco mais rápida que minha outra resposta - que não consegue lidar com os dois últimos casos de teste no TIO - e lida com todos os casos de teste em ~ 4 segundos.

Experimente online!

Como 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
fonte