Filling a matrix with smaller blocks

Question:

Given a n*m matrix.

[[0,0,0,0]
[0,0,0,0]
[0,0,0,0]
[0,0,0,0]]

Then we need to fill in the matrix with smaller blocks such that the new blocks occupy empty space and don’t overlap with existing blocks.

For example, after putting a block of 2*2, the matrix looks as below:

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

Return -1 if no space available in the bigger matrix.

My Code:

matrix_m = 4
matrix_n = 3

block_m = 2
block_n = 2

matrix = [[0]*matrix_n for _ in range(matrix_m)]
block = [[1]*block_n for _ in range(block_m)]

def solution(matrix, block):
    from collections import deque
    
    m = len(matrix)
    n = len(matrix[0])
    
    bm = len(block)
    bn = len(block[0])
    
    d = deque()
    for r in range(bm):
            for c in range(bn):
                d.append(block[r][c])
                
    
    for row in range(m):
        for col in range(n):
            if matrix[row][col] == 0:
                if d:
                    matrix[row][col] = d.popleft()
                else:
                    break
    
    return matrix
            

solution(matrix, block)

Output:

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

Expected Output:

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

How to modify the def(solution) to get the expected output?

Does the below logic looks correct to find the next available block?

    for i,row in enumerate(block):
        for j,val in enumerate(row):
            while i<m and j<n:
                if matrix[i][j] == 0:
                    if d:
                        matrix[i][j] = d.popleft()
                    else:
                        break
            i += 1
            j += 1
Asked By: meallhour

||

Answers:

this is an NP-Hard problem … it is known as rectangle packing you can find some various algorithms pretty easily, but it is a computationally hard problem.. that said here is a modified version that correectly fills the matrix with just this one square

def solution(matrix, block):
    # make a copy to not overwrite original
    m2 = copy.deepcopy(matrix)
    for i,row in enumerate(block):
        for j,val in enumerate(row):
            # fill some squares with the values from "block"
            m2[i][j] = val
    return m2 # return copy
Answered By: Joran Beasley