1

I have a problem that I am trying to find an algorithm for. I'd appreciate any suggestions.

I have n rows of length m. The rows have binary (0,1) values that have some expected sum. The 1's can be placed anywhere in its row as long as the sum is as expected. The goal is to minimize the vertical sum for each column in length m.

For example, if we have a 4 rows and 10 columns, where the expected sums are:

Row 1: 6

Row 2: 7

Row 3: 4

Row 4: 5

A potential solution could be:

1 1 1 1 1 1 0 0 0 0

1 1 1 0 0 0 1 1 1 1

1 0 0 1 1 1 0 0 0 0 

0 1 0 0 0 0 1 1 1 1

Getting vertical sums of:

3 3 2 2 2 2 2 2 2 2

Opposed to the larger sums if we would just place all the ones in the beginning:

1 1 1 1 1 1 0 0 0 0

1 1 1 1 1 1 1 0 0 0

1 1 1 1 0 0 0 0 0 0

1 1 1 1 1 0 0 0 0 0

With sums of:

4 4 4 4 3 2 1 0 0 0

So, I'm trying to spread out the load. My number of rows will get into the millions/billions, so I'm hoping for a linear algebra approach rather than iterative. Thanks!

kstisser
  • 13
  • 4

1 Answers1

2
def create_min_vert_matrix(num_r, num_c, arr_sum_rows): 
    res = [] 
    curr = 0 
    for r in range(num_r): 
        row = [0]*num_c 
        while arr_sum_rows[r] > 0: 
            arr_sum_rows[r] -= 1 
            row[curr] = 1 
            curr = (curr+1)%num_c 
        res.append(row) 
    return res

A quick test:

create_min_vert_matrix(4, 10, [6,7,4,5])                                                                       
[[1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [1, 1, 1, 0, 0, 0, 1, 1, 1, 1],
 [0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
 [1, 1, 0, 0, 0, 0, 0, 1, 1, 1]]

The function takes number of rows, num_r, number of columns, num_c, and an array that tells what the sum of the ones in each row has to be (arr_sum_rows).

The idea is if we distribute the one column-wise as evenly as possible, we are able to minimize the column sums. To make this happen, we keep track of the last column where we inserted a one, curr, and for each inserted one increment it. If it grows larger than the number of columns we set it to zero: curr = (curr+1)%num_c.

The algorithm runs in O(n*m) where n and m are the number of rows and columns of the matrix and O(1) extra space if we don't count the auxiliary space needed for the result (otherwise also O(n*m) extra space of course).

user1984
  • 5,990
  • 2
  • 13
  • 32
  • Thank you, this definitely works! I really appreciate your effort in solving this! My only hesitation is I was hoping for more of a quick linear algebra computation as my problem scales up into the millions/billions of rows (I'll update the problem with this). I'll leave this open another week to see if anyone comes up with that. If not I'll accept your answer. Thanks! – kstisser Nov 12 '21 at 13:37