<p>Given a <strong>0-indexed</strong> 2D integer matrix <code><font face="monospace">grid</font></code><font face="monospace"> </font>of size <code>n * m</code>, we define a <strong>0-indexed</strong> 2D matrix <code>p</code> of size <code>n * m</code> as the <strong>product</strong> matrix of <code>grid</code> if the following condition is met:</p>

<ul>
	<li>Each element <code>p[i][j]</code> is calculated as the product of all elements in <code>grid</code> except for the element <code>grid[i][j]</code>. This product is then taken modulo <code><font face="monospace">12345</font></code>.</li>
</ul>

<p>Return <em>the product matrix of</em> <code><font face="monospace">grid</font></code>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> grid = [[1,2],[3,4]]
<strong>Output:</strong> [[24,12],[8,6]]
<strong>Explanation:</strong> p[0][0] = grid[0][1] * grid[1][0] * grid[1][1] = 2 * 3 * 4 = 24
p[0][1] = grid[0][0] * grid[1][0] * grid[1][1] = 1 * 3 * 4 = 12
p[1][0] = grid[0][0] * grid[0][1] * grid[1][1] = 1 * 2 * 4 = 8
p[1][1] = grid[0][0] * grid[0][1] * grid[1][0] = 1 * 2 * 3 = 6
So the answer is [[24,12],[8,6]].</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> grid = [[12345],[2],[1]]
<strong>Output:</strong> [[2],[0],[0]]
<strong>Explanation:</strong> p[0][0] = grid[0][1] * grid[0][2] = 2 * 1 = 2.
p[0][1] = grid[0][0] * grid[0][2] = 12345 * 1 = 12345. 12345 % 12345 = 0. So p[0][1] = 0.
p[0][2] = grid[0][0] * grid[0][1] = 12345 * 2 = 24690. 24690 % 12345 = 0. So p[0][2] = 0.
So the answer is [[2],[0],[0]].</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= n == grid.length&nbsp;&lt;= 10<sup>5</sup></code></li>
	<li><code>1 &lt;= m == grid[i].length&nbsp;&lt;= 10<sup>5</sup></code></li>
	<li><code>2 &lt;= n * m &lt;= 10<sup>5</sup></code></li>
	<li><code>1 &lt;= grid[i][j] &lt;= 10<sup>9</sup></code></li>
</ul>

class Solution:
    def constructProductMatrix(self, grid: List[List[int]]) -> List[List[int]]:
        #flat = reduce(lambda x, y: x + y, grid)
        flat = list(chain.from_iterable(grid))

        #ff = list(accumulate(flat[:len(flat)-1], operator.mul))
        #ff = flat
        #fb = ff
        #fb = list(reversed(list(accumulate(reversed(flat[1:]), operator.mul))))
        ff = list(accumulate(flat[:len(flat)-1], lambda a, b: (a % 12345 * b % 12345) % 12345))
        fb = list(reversed(list(accumulate(reversed(flat[1:]), lambda a, b: (a % 12345 * b % 12345) % 12345))))

        def batched(iterable, n):
            if n < 1:
                raise ValueError('n must be at least one')
            iterator = iter(iterable)
            while batch := list(islice(iterator, n)):
                yield batch

        result = chain([fb[0] % 12345], map(lambda x: (x[0]% 12345 * x[1]% 12345) % 12345, zip(ff[:-1], fb[1:])), [ff[-1] % 12345])
        return(list(batched(result, len(grid[0]))))


        # return None
        # f = -1
        # b = len(fb) - 2

        # while f < len(ff)-1 and b >= -1:
        #     a = 1
        #     if f == -1:
        #         print(fb[b])
        #     elif b == -1:
        #         print(ff[f])
        #     else:
        #         print(ff[f] * fb[b])
        #     f += 1
        #     b -= 1
        # return None


        # flat = list(reduce(lambda x, y: x + y, grid))
        # p = 0
        # lj = len(grid[0])
        # for i in range(len(grid)):
        #     for j in range(lj):
        #         if p == 0:
        #             grid[i][j] = reduce(lambda a, b: a * b, flat[p+1:]) % 12345
        #         elif p +1 == len(flat):
        #             grid[i][j] =reduce(lambda a, b: a * b, flat[0:p]) % 12345
        #         else:
        #             grid[i][j] = reduce(lambda a, b: a * b, flat[0:p]) * reduce(lambda a, b: a * b, flat[p+1:]) % 12345
        #         p += 1
        # return grid

        # v = reduce(lambda x, y: x * reduce(lambda a, b: a * b, y), grid, 1)
        # if v == 0:
        #     print(v)
        #     return None
        # #print(v)
        # #return #
        # lj = len(grid[0])
        # for i in range(len(grid)):
        #     for j in range(lj):
        #         grid[i][j] = (v // grid[i][j]) % 12345
        # return grid

        # result = list()
        # for row in grid:
        #     new_row = list()
        #     for col in row:
        #         new_row.append(int(v // col) % 12345)
        #     result.append(new_row)
        # return result

        
53900