Podziel siatkę na siatkę

22

Wprowadzenie

Jest mała wioska z kilkoma domami i pustymi polami. Lokalni biurokraci chcą podzielić wioskę na działki, tak aby każda działka zawierała dokładnie jeden dom, a granice działek tworzą ładną linię prostą. Twoim zadaniem jest ustalenie, czy jest to możliwe.

Zadanie

Twoje dane wejściowe to prostokątna tablica bitów 2D; 1 oznacza dom, a 0 puste pole. Jego rozmiar będzie wynosił co najmniej 1 × 1 i będzie zawierał co najmniej jeden 1. Możesz pobrać dane wejściowe w dowolnym rozsądnym formacie (zagnieżdżona lista liczb całkowitych, lista ciągów, ciąg wielowierszowy itp.).

Twój program określi, czy tablicę można podzielić na komórki siatki za pomocą prostych linii poziomych i pionowych, tak aby każda komórka siatki zawierała dokładnie jedną 1. Komórki siatki mogą mieć różne rozmiary i kształty, chociaż zawsze będą prostokątne. Linie muszą przebiegać od jednej krawędzi tablicy do drugiej krawędzi.

Na przykład poniżej podano poprawny podział tablicy:

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

mając na uwadze, że następujący podział nie jest prawidłowy, ponieważ istnieją komórki siatki bez 1 lub więcej niż 1:

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

Jeśli istnieje prawidłowy podział, należy podać wartość zgodną z prawdą, a w przeciwnym razie wartość fałsz.

Zasady i punktacja

Możesz napisać pełny program lub funkcję. Wygrywa najniższa liczba bajtów.

Przypadki testowe

[[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
źródło
można podzielić [[0,0,1,0,1], [1,0,0,1,0], [0,0,0,1,0]] na: 3X1, 2X1, 3X2, 2X1, Prostokąty 2X1 w ten sposób czy nie? 001 | 01 --- + - 100 | 10 + - 000 | 10
officialaimm
4
@officialaimm Nie, to nie jest poprawne. Linie siatki muszą przebiegać od jednej strony tablicy do drugiej strony.
Zgarb
Proponowany przypadek testowy: [[1, 0, 1], [0, 1, 0], [1, 0, 0]]była to jedyna matryca 3x3, dla której moje nowe podejście zawiodło.
Dennis
@Dennis Dzięki, dodano.
Zgarb

Odpowiedzi:

7

Pyth, 30 29 26 24 23 bajtów

sm.Asmmq1ssbCkds./MC./M

Wypróbuj online.

Jestem pewien, że będzie krótszy. Jest to O (2 min ) , w którym m i n są szerokość i wysokość matrycy, lecz kończy się dwa ostatnie testów w ciągu 45 sekund na laptopie z baterii (i5-5200U z ograniczoną skuteczności).

Wyświetla liczbę rozwiązań.

Wyjaśnienie

Praca z pięciowymiarowymi tablicami jest naprawdę przyjemna. </sarcasm> Nie powinieneś rozumieć, jak to działa, nawet z wyjaśnieniem.

                    ./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
źródło
2

Haskell , 116 bajtów

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

Wypróbuj online!

Roman Czyborra
źródło
1
To się nie kompiluje. Usuń swoją odpowiedź, dopóki nie zostanie naprawiona. Istnieje również duży potencjał golfowy, np. zmiana nazwy mergerowsna m.
Laikoni
Chciałem skończyć z konkurencją ze względu na trudną do pokonania zwięzłość Pytha i dziękuję tobie @Laikoni za wykrycie, że prawdopodobnie pomieszałem nawiasy klamrowe.
Roman Czyborra
2
To niepoprawnie włącza False [[1,0],[0,1],[1,0]]. Problem polega na tym, że zachłanne załamanie może przeszkadzać później.
xnor
Rzeczywiście, mój [[1,1],[1,0]]upadek fałszywie utrudnia [[1],[1],[1]]rozwiązanie. Pozwól mi się przespać, czy powinienem usunąć?
Roman Czyborra
1

Galaretka , 20 bajtów

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

To wciąż rozwiązanie brutalnej siły, ale jest nieco szybsze niż moja inna odpowiedź - która nie radzi sobie z dwoma ostatnimi przypadkami testowymi na TIO - i obsługuje wszystkie przypadki testowe w ~ 4 sekund.

Wypróbuj online!

Jak to działa

ŒṖ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
źródło