Diagonalização do bloco de custo mínimo


10

Considere matrizes diagonais de bloco binário que possuem blocos quadrados de 1s na diagonal principal e são 0 em qualquer outro lugar. Vamos chamar essas matrizes de matrizes "válidas".

Por exemplo, aqui estão algumas matrizes 4x4 válidas:

1 0 0 0     1 1 0 0     1 0 0 0     1 0 0 0     1 1 0 0    1 1 1 1
0 1 0 0     1 1 0 0     0 1 1 0     0 1 1 1     1 1 0 0    1 1 1 1
0 0 1 0     0 0 1 0     0 1 1 0     0 1 1 1     0 0 1 1    1 1 1 1
0 0 0 1     0 0 0 1     0 0 0 1     0 1 1 1     0 0 1 1    1 1 1 1

Observe que uma maneira alternativa de descrever essas matrizes é que existe uma cadeia de blocos quadrados 1 do canto superior esquerdo para o canto inferior direito, tocando de canto a canto, e em qualquer outro lugar é 0.

Por outro lado, aqui estão algumas matrizes 4x4 inválidas:

1 0 1 0     1 0 1 0     1 1 0 0     0 1 1 1     1 1 0 0    0 0 0 0
0 1 1 1     0 1 0 1     1 1 0 0     0 1 1 1     1 1 0 0    0 0 0 0
1 0 0 1     1 0 1 0     0 0 0 0     0 1 1 1     1 1 0 0    0 0 0 0
0 0 1 0     0 1 0 1     0 0 0 1     1 0 0 0     0 0 1 1    0 0 0 0

Você será dado um npor nmatriz binária como entrada - o que é o número mínimo de 0bits que você precisa definir para 1a fim de obter uma matriz válida?

Você pode escrever uma função ou programa nutilizando qualquer formato conveniente de string, lista ou matriz representando uma nmatriz de 0s e 1s (desde que não seja pré-processado). As linhas devem ser claramente separadas de alguma forma, para que formatos como uma matriz 1D de bits não sejam permitidos.

Isso é , portanto, o objetivo é minimizar o número de bytes no seu programa.

Exemplos

Por exemplo, se a entrada for

0 0 0 0 0
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 1

a resposta é 5, pois você pode definir cinco 0bits 1para obter:

1 0 0 0 0
0 1 1 0 0
0 1 1 0 0
0 0 0 1 0
0 0 0 0 1

e este é o número mínimo necessário. No entanto, se a entrada foi

0 0 0 0 1
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

então a resposta é 24, já que a única matriz 5x5 válida onde está o canto superior direito 1é a matriz de todos os 1s.

Casos de teste

Os testes são representados aqui como uma matriz 2D de números inteiros.

[[0]] -> 1
[[1]] -> 0
[[0,1],[0,0]] -> 3
[[1,0],[0,0]] -> 1
[[0,0,0],[0,1,0],[0,0,0]] -> 2
[[0,1,0],[0,0,0],[0,1,0]] -> 7
[[0,1,0],[1,0,0],[0,0,1]] -> 2
[[1,1,1],[1,1,1],[1,1,1]] -> 0
[[0,0,0,0],[0,0,1,0],[0,1,0,0],[0,0,0,0]] -> 4
[[0,0,1,0],[0,0,0,0],[0,0,0,0],[0,0,0,1]] -> 8
[[0,0,1,0],[0,0,0,0],[0,0,0,0],[0,0,1,0]] -> 14
[[0,0,1,0],[0,0,0,0],[0,0,0,0],[0,1,0,0]] -> 14
[[0,0,0,0,0],[0,0,0,0,0],[0,1,0,0,0],[0,0,0,0,1],[0,0,0,0,0]] -> 7
[[0,0,0,0,0],[0,0,0,0,0],[1,0,0,0,0],[0,0,0,0,1],[0,0,0,0,0]] -> 11
[[0,0,0,0,0],[0,0,1,0,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,1]] -> 5
[[0,0,0,0,1],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0]] -> 24
[[0,0,0,1,0],[0,0,0,0,1],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0]] -> 23
[[0,1,0,0,0],[1,0,0,0,0],[0,0,1,0,0],[0,0,0,0,1],[0,0,0,1,0]] -> 4
[[0,1,1,1,0],[0,1,1,0,1],[0,1,1,1,0],[0,1,0,0,1],[0,0,0,0,0]] -> 14

Notas

Respostas:


3

MATL , 46 43 bytes

nX^tQt:qZ^!tsb=Z)"@!"@1$l]@n$YdG-Q?6MG>zvX<

Entrada é uma matriz 2D com ponto e vírgula como separador de linhas. Por exemplo, a entrada para o último caso de teste é

[0,1,1,1,0;0,1,1,0,1;0,1,1,1,0;0,1,0,0,1;0,0,0,0,0]

Experimente online! Ou verifique todos os casos de teste (código ligeiramente modificado para receber todas as entradas; os resultados aparecem após alguns segundos)

Explicação

Deixe a entrada ser uma N × N matriz. O código primeiro calcula todos os ( N +1) -tuplos de tamanhos de bloco que produzem o tamanho de matriz apropriado. Por exemplo, para N = 4, os tuplos são 0 0 0 0 4, 0 0 0 1 3, ..., 4 0 0 0 0. Para cada tupla, cria a matriz diagonal do bloco com esses tamanhos de bloco. Em seguida, verifica se a matriz cobre todas as 1entradas da entrada e, se assim for, toma nota do número de 1entradas que não estavam presentes na entrada. O resultado final é o mínimo de todos os números obtidos.

nX^      % Implicit input  an N×N matrix. Get N
t        % Duplicate N
Qt:q     % Vector [0 1 ... N]
Z^       % Cartesian power. Gives 2D array
!ts      % Transpose, duplicate, sum of each column
b=       % Logical vector that equals true if the sum is N
Z)       % Filter columns according to that. Only keep columns that sum to N. Each 
         % column is the size of one block
"        % For each column
  @      %   Push that column
  "      %   For each entry of that column
    @    %     Push that entry
    1$l  %     Square matrix with that size, filled with 1
  ]      %   End
  @n     %   Column size. This is the number of blocks in the block-diagonal matrix
  $Yd    %   Build block-diagonal matrix from those blocks
  G-Q    %   Subtract input matrix element-wise, and add 1
  ?      %   If all entries are nonzero (this means each that entry that is 1 in the
         %   block-diagonal matrix is also 1 in the input matrix)
    6M   %   Push block-diagonal matrix again
    G>   %   For each entry, gives 1 if it exceeds the corresponding entry of the
         %   input, that is, if the block-diagonal matrix is 1 and the input is 0
    z    %   Number of 1 entries
    v    %   Concatenate vertically with previous values
    X<   %   Take minimum so far
         %   Implicit end
         % Implicit end
         % Implicit display

3

Python com numpy, 102

from numpy import*
lambda M:sum(diff([k for k in range(len(M)+1)if(M|M.T)[:k,k:].any()-1])**2)-M.sum()

Um algoritmo eficiente. Localiza os "pontos do pescoço" na diagonal que podem separar os blocos. Estes têm todos os 0's acima e à direita, assim como abaixo e à esquerda. Os blocos mínimos são aqueles entre os pontos do pescoço.

??000
??000
00???
00???
00???

O comprimento de um bloco é a diferença entre os pontos consecutivos do pescoço, portanto, sua área total da soma dos quadrados destes. Subtrair a soma da matriz original fornece o número de inversões necessárias de 0 a 1.


2

Pitão, 45 bytes

-hSlMf@I.DRlQx1sQTms.b^+LsYN2d+0._ds.pM./lQss

Tarefa difícil, por isso é bastante longa.

Experimente on-line: Demonstration or Test Suite

Explicação:

s.pM./lQcalcula todas as partições inteiras de len(matrix). ms.b^+LsYN2d+0._dconverte-os em pares de coordenadas. Por exemplo, a partição [1, 2, 2]de 5é convertida em [[0,0], [1,1], [1,2], [2,1], [2,2], [3,3], [3,4], [4,3], [4,4].

f@I.DRlQx1sQTem seguida, filtra as partições que se sobrepõem completamente à matriz ( .DRlQx1sQcalcula todos os pares de coordenadas das células ativas na matriz).

-hSlM...ss conta as células de cada partição restante, escolhe aquela com menos células e subtrai as células já ativas.


0

Matrizes , 180 bytes (não concorrentes )

Matricks é um novo esolang que criei muito recentemente para lidar com problemas de matriz (como este), tendo apenas dois tipos de dados: floats e matrizes. Ele ainda não está totalmente em destaque e ainda possui muitas operações ausentes (precisei adicionar algumas funcionalidades para esse desafio). Enfim, aqui está o código:

il=1:j3;:bdx;;;s1::L;j1;;
b{q:1;mgr:c;|gc:r;|(r=c)|(gr-1:c;|gr:c+1;)&(rec)|(gr+1:c;|gr:c-1;)&(cer):l:L;};z:(l-1)/2;B1;s1::g1:;-1;ig1:;=0:j2;:j1;;
s1::d{q:1;};;kg1:;-g:;;
kg:;*-1+1;

Explicação

A primeira parte, il=1:j3;:...;verifica se a matriz é do tamanho 1. Se for, ela salta para a última linha kg:;*-1+1;, que é uma 0 <-> 1função simples .

Caso contrário, ele continuará com o restante do código. bdx;;;define a célula 0,0para a soma atual e s1::L;j1;cria um contador na célula na linha abaixo.

A próxima linha é um pouco mais complicada. É um loop que executa ntempos, nsendo o tamanho da matriz. Vou usar o terceiro caso de teste como exemplo. Quando chegamos à segunda linha, a matriz fica assim:

1 0 1
2 0 0

Primeiro, vamos à compreensão da matriz {q:1;m...;}. Isso faz a diagonal e tenta o máximo possível para limpar 0 que precisa ser preenchido. Tudo isso é realizado usando operadores booleanos simples. Em seguida, anexamos à matriz atual, fornecendo o seguinte:

    V--data we want to keep
1 1 1 0 1 <-|
1 1 2 0 0 <-- old matrix

Em seguida, cortamos a matriz antiga usando z:(l-1)/2;e giramos a matriz inteira para a esquerda usando B1;. Isso nos dá uma matriz pronta para a próxima iteração, parecida com:

1 1 1
2 1 1

Por fim, diminuímos o contador, verificamos e continuamos com ig1:;=0:j2;:j1;;

Uma vez que o loop é interrompido, encontramos a nova soma e definimos o antigo local do contador s1::d{q:1;};;. Finalmente, pegamos a diferença e retornamos kg1:;-g:;;. kdefine a matriz atual como um valor e a impressão está implícita.

...

Como você pode ver, o Matricks é bastante detalhado e não é uma linguagem de golfe muito boa. Mas diabos, eu queria mostrar isso.

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.