Diagonalizzazione del blocco di costo minimo


10

Considera le matrici diagonali a blocchi binari che hanno blocchi quadrati di 1s sulla diagonale principale e sono 0 ovunque. Chiamiamo tali matrici "valide".

Ad esempio, ecco alcune matrici 4x4 valide:

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

Si noti che un modo alternativo per descrivere tali matrici è che esiste una catena di blocchi quadrati 1 da in alto a sinistra a in basso a destra, che toccano un angolo all'altro e ovunque è 0.

Per contrasto, ecco alcune matrici 4x4 non valide:

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

Vi sarà data una nda nmatrice binaria come input - qual è il numero minimo di 0bit è necessario insieme al 1al fine di ottenere una matrice valida?

Si può scrivere una funzione o presa programma in qualsiasi formato stringa conveniente, lista o una matrice che rappresenta un ndalla nmatrice di 0 e 1 (fintanto che non viene pre-elaborata). Le righe devono essere chiaramente separate in qualche modo, quindi non sono consentiti formati come un array di bit 1D.

Questo è , quindi l'obiettivo è ridurre al minimo il numero di byte nel programma.

Esempi

Ad esempio, se l'ingresso è

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

quindi la risposta è 5, poiché è possibile impostare cinque 0bit 1per ottenere:

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 questo è il numero minimo richiesto. Tuttavia, se l'input era

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

allora la risposta è 24, poiché l'unica matrice 5x5 valida in cui è in alto a destra 1è la matrice di tutte le 1s.

Casi test

I test sono rappresentati qui come una matrice 2D di numeri interi.

[[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

Appunti

Risposte:


3

MATL , 46 43 byte

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

L'input è un array 2D con punto e virgola come separatore di riga. Ad esempio, l'ingresso per l'ultimo caso di test è

[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]

Provalo online! Oppure verifica tutti i casi di test (codice leggermente modificato per accettare tutti gli input; i risultati compaiono dopo pochi secondi)

Spiegazione

Lascia che l'ingresso sia una matrice N × N. Il codice prima calcola tutte le taglie ( N +1) delle dimensioni del blocco che producono la dimensione della matrice appropriata. Ad esempio, per N = 4 le tuple sono 0 0 0 0 4, 0 0 0 1 3..., 4 0 0 0 0. Per ogni tupla crea la matrice diagonale a blocchi con quelle dimensioni di blocco. Quindi controlla se la matrice copre tutte le 1voci nell'input e, in tal caso, prende nota del numero di 1voci che non erano presenti nell'input. Il risultato finale è il minimo di tutti i numeri ottenuti.

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 con 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()

Un algoritmo efficiente. Trova i "punti del collo" sulla diagonale che possono separare i blocchi. Questi hanno tutti gli 0 in alto e a destra, così come in basso e a sinistra. I blocchi minimi sono quelli tra le punte del collo.

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

La lunghezza di un blocco è la differenza tra i punti del collo consecutivi, quindi la loro area totale della somma dei quadrati di questi. Sottraendo la somma della matrice originale si ottiene quindi il numero di lanci necessari da 0 a 1.


2

Pyth, 45 byte

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

Compito difficile, quindi è piuttosto lungo.

Provalo online: dimostrazione o Test Suite

Spiegazione:

s.pM./lQcalcola tutte le partizioni intere di len(matrix). ms.b^+LsYN2d+0._dli converte in coppie di coordinate. Ad esempio, la partizione [1, 2, 2]di 5viene convertita in [[0,0], [1,1], [1,2], [2,1], [2,2], [3,3], [3,4], [4,3], [4,4].

f@I.DRlQx1sQTquindi filtra per le partizioni, che si sovrappongono completamente alla matrice ( .DRlQx1sQcalcola tutte le coppie di coordinate delle celle attive nella matrice).

-hSlM...ss conta le celle di ogni partizione rimanente, sceglie quella con il minor numero di celle e sottrae le celle già attive.


0

Matrick , 180 byte (non competitivi)

Matricks è un nuovo esolang che ho creato di recente per affrontare problemi di matrice (come questo), avendo solo 2 tipi di dati: float e matricies. Non è ancora completamente descritto e ha ancora molte operazioni mancanti (ho dovuto aggiungere alcune funzionalità per questa sfida). Comunque, ecco il codice:

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;

Spiegazione

La prima parte il=1:j3;:...;verifica se la matrice ha dimensioni 1. In caso affermativo, passa all'ultima riga kg:;*-1+1;, che è una 0 <-> 1funzione semplice .

Altrimenti, continua con il resto del codice. bdx;;;imposta la cella 0,0sulla somma corrente e s1::L;j1;crea un contatore nella cella nella riga seguente.

La riga successiva è un po 'più complicata. È un ciclo che scorre i ntempi, nessendo la dimensione della matrice. Userò il terzo caso di test come esempio. Quando arriviamo alla seconda riga, la matrice è simile alla seguente:

1 0 1
2 0 0

Innanzitutto, entriamo nella comprensione della matrice {q:1;m...;}. Questo rende la diagonale e fa del suo meglio per ripulire 0 che è necessario compilare. Tutto questo viene realizzato utilizzando semplici operatori booleani. Quindi, lo anteponiamo alla matrice corrente, dando questo:

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

Quindi, tagliamo la vecchia matrice usando z:(l-1)/2;e ruotiamo l'intera matrice verso sinistra usando B1;. Questo ci dà una matrice pronta per la prossima iterazione, simile a:

1 1 1
2 1 1

Infine, decrementiamo il contatore, lo controlliamo e continuiamo con ig1:;=0:j2;:j1;;

Una volta che il loop è terminato, troviamo la nuova somma e impostiamo il vecchio punto del contatore con s1::d{q:1;};;. Infine, prendiamo la differenza e torniamo kg1:;-g:;;.kimposta l'array corrente su un valore e la stampa è implicita.

...

Come puoi vedere, Matricks è piuttosto prolisso e non è un ottimo linguaggio per giocare a golf. Ma diamine, volevo metterlo in mostra.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.