Sandpile Tray
MediumOnline Assessment
Drop grains of sand one at a time onto a tray with drains, and report every avalanche and how many grains the tray loses.
The tray is a grid. Each cell of tray is a digit 0 to 3, the number of grains lying there, or #, a drain. Grains that reach a drain disappear.
A grain is dropped at each position of drops, in order ([row, col], counted from 0 at the top left). Dropping a grain adds 1 to that cell, then the tray settles before the next drop:
- Whenever a non-drain cell holds 4 or more grains, it topples: it loses 4 grains and each of its four neighbours (up, down, left, right) receives 1. A grain sent beyond the edge of the grid is lost, and a grain sent onto a drain is lost. A cell that still holds 4 or more grains after toppling topples again.
- Toppling continues until every non-drain cell holds at most 3 grains. (The final result does not depend on the order in which you topple cells.)
- A grain dropped directly onto a drain is lost at once and nothing topples.
For each drop, record the avalanche as [topples, cells]: the total number of topples that happened during that settling (a cell that toppled three times counts three), and the number of different cells that toppled at least once. A drop that causes no topple records [0, 0].
Input: tray, a list of equal-length strings of digits 0-3 and #; drops, a list of [row, col] positions inside the grid.
Output: a list [final_tray, avalanches, lost]: the tray after all drops in the same string format (drains stay #), the list of [topples, cells] pairs, one per drop, and lost, the total number of grains lost over all the drops, through the edges and into drains (including grains dropped directly on drains).
Example 1
- Input:
- [["333","333","333"],[[1,1],[1,1]]]
- Output:
- [["131","313","131"],[[10,9],[0,0]],12]
- Explanation
- A 3x3 tray of 3s; one grain on the centre makes 4, so the centre topples and each side cell gets a 4th grain. The four side cells topple: each sends one grain back to the centre, one to each of two corners, and one off the edge. The centre now has 4 again and topples a second time, while each corner, with 5, topples once and sends two grains off the edge. In total 10 topples by 9 different cells (the centre toppled twice) and 12 grains lost. The second drop lands on the centre, which holds 0 after the chain, so nothing topples:
[0, 0].
Example 2
- Input:
- [["3#","33"],[[0,1],[1,0],[0,0]]]
- Output:
- [["1#","20"],[[0,0],[3,3],[0,0]],9]
- Explanation
["3#","33"]: the first drop lands on the drain, so that grain is lost with[0, 0]. The grain at bottom-left makes 4: it topples, losing two grains over the edges and giving one each to the cell above and the cell to its right. Both of those now hold 4 and topple too (3 topples, 3 cells); their grains that fall onto the drain or over an edge are lost. The last drop adds one grain to the empty top-left cell. Nine grains were lost in total.
Example 3
- Input:
- [["0321"],[[0,1],[0,1],[0,2],[0,0]]]
- Output:
- [["2202"],[[1,1],[0,0],[1,1],[0,0]],4]
- Explanation
- A single row
0321. Drop at column 1 (3 becomes 4): it topples, with the cells above and below being off the grid (2 lost), leaving1 0 3 1. The second drop at column 1 gives 1 grain, no topple. The drop at column 2 (3 becomes 4) topples to1 2 0 2with 2 more lost. The last drop at column 0 gives2 2 0 2; 4 lost in all.
Constraints
- 1 ≤ tray.length ≤ 10 and 1 ≤ tray[0].length ≤ 10; characters are 0, 1, 2, 3 or #
- 0 ≤ drops.length ≤ 150; every drop position is inside the tray