1

I'm stuck with a problem of generating equations from a 2-D array input. The equations just need to sum up the rows and columns alogn with a variable (having the i,j indexes)

Example :

Input :
[1 2 3 4 5
 6 7 8 9 10
 11 12 13 14 15
]

Outputs :
1. (row-sum with Xs) : 
x11*1 + x12*2 + x13*3 + x14*4 + x15*5 
x21*6 + x22*7 + x23*8 + x24*9 + x25*10 
x31*11 + x32*12 + x33*13 + x34*14 + x35*15 

2. (column-sum with Xs) :
x11*1 + x21*6 + x31*11
x12*2 + x22*7 + x31*12
x13*3 + x23*8 + x33*13
x14*4 + x24*9 + x34*14
x15*5 + x25*10 + x35*15

what would be the most efficient way to write when the input may change ? Input could be a 2-dimensional or 3-dimensional array but not more than that.

Shankar Pandey
  • 451
  • 1
  • 4
  • 22

1 Answers1

0

I don't understand the output you want with a 3-dimensional list (list of lists of lists), but hopefully, this can be a good start.

def to_eq(coeffs: list, column_sum: bool = False, var: str = 'x') -> str:
    if column_sum: # Transpose the input list of lists
        coeffs = [list(k) for k in zip(*coeffs)]
        output = '\n'.join(
            ' + '.join(var + str(j+1) + str(i+1) for j, coeff in enumerate(line)) 
            for i, line in enumerate(coeffs)
        )
    else: 
        output = '\n'.join(
            ' + '.join(var + str(i+1) + str(j+1) for j, coeff in enumerate(line)) 
            for i, line in enumerate(coeffs)
        )
    return output

It looks repetitive, but since you want an efficient implementation, I took the if outside. The reversing of i, j to match your example can probably be made in a single line by someone with a little more creativity than me. I don't know if you actually meant that in your example though. The usual notation is to have the row first and then the column, that is, ij.

>>> coeffs = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]]
>>> to_eq(coeffs)
    x11 + x12 + x13 + x14 + x15
    x21 + x22 + x23 + x24 + x25
    x31 + x32 + x33 + x34 + x35
>>> to_eq(coeffs, column_sum=True)
    x11 + x21 + x31
    x12 + x22 + x32
    x13 + x23 + x33
    x14 + x24 + x34
    x15 + x25 + x35

By the way, there are a ton of ways to transpose a list of lists. Check that out for other options besides what I used here.

Some tests:

>>> cols = 100000
>>> max_ = 10000000
>>> coeffs = [[i + j for i in range(cols)] for j in range(0, max_, cols)]
>>> print(len(coeffs), ' by ', len(coeffs[0]))
    100  by  100000

>>> %timeit to_eq(coeffs)
    5.66 s ± 90.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
>>> %timeit to_eq(coeffs, column_sum=True)
    6.28 s ± 118 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

>>> cols = 1000
>>> max_ = 10000
>>> coeffs = [[i + j for i in range(cols)] for j in range(0, max_, cols)]
>>> print(len(coeffs), ' by ', len(coeffs[0]))
    10  by  1000

>>> %timeit to_eq(coeffs)
    5.59 ms ± 308 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)  
>>> %timeit to_eq(coeffs, column_sum=True)
    5.98 ms ± 111 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Camilo Martinez M.
  • 1,420
  • 1
  • 7
  • 21