Разделить сетку на сетку

22

Введение

Есть небольшая деревня, в которой только несколько домов и пустые поля. Местные бюрократы хотят разделить деревню на участки, чтобы каждый участок содержал ровно один дом, а границы участков образуют красивую прямолинейную сетку. Ваша задача - определить, возможно ли это.

Задание

Ваш вход представляет собой прямоугольный двумерный массив битов; 1 представляет дом, а 0 - пустое поле. Его размер будет по крайней мере 1 × 1 , и он будет содержать по крайней мере один 1. Вы можете взять ввод в любом разумном формате (вложенный список целых чисел, список строк, многострочная строка и т. Д.).

Ваша программа должна определить, можно ли разбить массив на ячейки сетки, используя прямые горизонтальные и вертикальные линии, чтобы каждая ячейка сетки содержала ровно одну единицу. Ячейки сетки могут иметь разные размеры и формы, хотя они всегда будут прямоугольными. Линии должны проходить от одного края массива до противоположного края.

Например, следующее является допустимым разделением массива:

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

тогда как следующее деление недопустимо, так как существуют ячейки сетки без 1 или более 1:

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

Если допустимое деление существует, вы должны вывести истинное значение, а в противном случае ложное значение.

Правила и оценки

Вы можете написать полную программу или функцию. Побеждает самое низкое число байтов.

Контрольные примеры

[[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
источник
можно [[0,0,1,0,1], [1,0,0,1,0], [0,0,0,1,0]] разделить на: 3X1, 2X1, 3X2, 2X1, 2X1 прямоугольники таким образом или нет? 001 | 01 --- + - 100 | 10 + - 000 | 10
officialaimm
4
@officialaimm Нет, это недействительно. Линии сетки должны проходить от одной стороны массива до другой стороны.
Згарб
Предлагаемый контрольный пример: [[1, 0, 1], [0, 1, 0], [1, 0, 0]]это была единственная матрица 3х3, для которой мой новый подход не удался.
Деннис
@ Деннис Спасибо, добавил.
Згарб

Ответы:

7

Pyth, 30 29 26 24 23 байта

sm.Asmmq1ssbCkds./MC./M

Попробуйте онлайн.

Я уверен, что это станет короче. Это O (2 mn ) , где m и n - ширина и высота массива, но завершает последние два теста за 45 секунд на моем ноутбуке от батареи (i5-5200U с ограниченной производительностью).

Выводит количество решений.

объяснение

С пятимерными массивами работать очень интересно. </ sarcasm> Вы не должны понимать, как это работает, даже с объяснениями.

                    ./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
источник
2

Haskell , 116 байт

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

Попробуйте онлайн!

Роман Чиборра
источник
1
Это не компилируется. Пожалуйста, удалите ваш ответ, пока он не будет исправлен. Существует также большой потенциал для игры в гольф, например. переименование mergerowsв m.
Лайкони
Я планировал выйти из соревнования из-за непревзойденной краткости Пита и поблагодарить тебя @Laikoni за то, что заметил, что я, вероятно, испортил свои брекеты для отступов.
Роман Чиборра
2
Это неправильно дает False на [[1,0],[0,1],[1,0]]. Проблема в том, что жадный крах может помешать более позднему лучшему краху.
xnor
Действительно, мой [[1,1],[1,0]]крах ложно мешает [[1],[1],[1]]решению проблемы. Позвольте мне спать по этому или я должен удалить?
Роман Чиборра
1

Желе , 20 байт

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

Это все еще грубое решение, но оно намного быстрее, чем мой другой ответ - который не справляется с последними двумя тестовыми примерами на TIO - и обрабатывает все тестовые случаи за ~ 4 секунды.

Попробуйте онлайн!

Как это работает

ŒṖ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.
Деннис
источник