# CGAC2022 Day 15: Chimney cleaning, Part 2

Part of Code Golf Advent Calendar 2022 event. See the linked meta post for details.

While other Elves are busy carrying air blowers, Fen comes and shouts, "I've got a spell for this job!"

To recap, a chimney is modeled as a rectangular grid. The number in each cell represents the amount of smoke in the region. The left and right sides are walls, and the top and bottom are open.

||========||
||  |90|  ||
||--+--+--||
||  |  |24||
||--+--+--||
||36|12|  ||
||--+--+--||
||  |  |  ||
||--+--+--||
||  |50|  ||
||========||


Fen can use "Vick" spell at a selected cell in the grid. When he uses it, the following happens:

1. The smoke at the selected cell is blown into three cells above it. Upper left and upper right cells get floor(n/4) amount of smoke each (if such cells exist) and the remaining smoke goes to the upper middle cell.
|  |   |  |    |12|26|12|
+--+---+--+ -> +--+--+--+
|  |50*|  |    |  |  |  |

||   |  |...    ||10| 3|...
||---+--+... -> ||--+--+...
||13*|  |...    ||  |  |...

2. The Vick spell itself moves to the cell above it.
3. The steps 1 and 2 are repeated until the Vick spell escapes the chimney.

Given the initial state above, casting Vick spell on the 50 (row 5, column 2) will result in the following:

||=========||
||  |90 |  ||
||--+---+--||
||  |   |24||
||--+---+--||
||36|12 |  ||
||--+---+--||
||  |   |  ||
||--+---+--||
||  |50*|  ||
||=========||

||=========||
||  |90 |  ||
||--+---+--||
||  |   |24||
||--+---+--||
||36|12 |  ||
||--+---+--||
||12|26*|12||
||--+---+--||
||  |   |  ||
||=========||

||=========||
||  |90 |  ||
||--+---+--||
||  |   |24||
||--+---+--||
||42|26*|6 ||
||--+---+--||
||12|   |12||
||--+---+--||
||  |   |  ||
||=========||

||=========||
||  |90 |  ||
||--+---+--||
||6 |14*|30||
||--+---+--||
||42|   |6 ||
||--+---+--||
||12|   |12||
||--+---+--||
||  |   |  ||
||=========||

||=========||
||3 |98*|3 ||
||--+---+--||
||6 |   |30||
||--+---+--||
||42|   |6 ||
||--+---+--||
||12|   |12||
||--+---+--||
||  |   |  ||
||=========||

||=========||
||3 |   |3 ||
||--+---+--||
||6 |   |30||
||--+---+--||
||42|   |6 ||
||--+---+--||
||12|   |12||
||--+---+--||
||  |   |  ||
||=========||


Given a 2D grid of non-negative integers which represents the current state of smoke in the chimney, and the initial position of the Vick spell, simulate the chimney as specified above and output the resulting state. You may assume that the chimney is at least 2 units wide and 2 units tall, and the Vick spell starts inside the chimney. The coordinates may be either 1- or 0-indexed.

Standard rules apply. The shortest code in bytes wins.

## Test cases

[[0, 90, 0], [0, 0, 24], [36, 12, 0], [0, 0, 0], [0, 50, 0]], (5, 2)
-> [[3, 0, 3], [6, 0, 30], [42, 0, 6], [12, 0, 12], [0, 0, 0]]

[[3, 0, 3], [6, 0, 30], [42, 0, 6], [12, 0, 12], [0, 0, 0]], (4, 1)
-> [[0, 11, 3], [0, 12, 30], [0, 3, 6], [0, 0, 12], [0, 0, 0]]

• Suggest a testcase that, there are non-zero values under initial position of Vick spell. For example, [[0, 90, 0], [0, 0, 24], [36, 12, 0], [0, 0, 0], [0, 50, 0]], (3, 2). Currently, the input y is actually not used.
– tsh
Commented Dec 15, 2022 at 5:46

# Python3, 159 bytes:

def f(b,x,y):
while x>=0:
c=(C:=b[x][y])//4
b[x][y]=0;x-=1
if x>=0:
for Y in[1,-1]:
if 0<=y+Y<len(b[0]):b[x][y+Y]+=c;C-=c
b[x][y]+=C
return b


Try it online!

# Charcoal, 67 bytes

≔§θηεＷη«≔§εζδ§≔εζ⁰≦⊖η≔§θηεＵＭε⁺κ⎇⁼λζ⁻δ×÷δ⁴№↔Ｅε⁻νζ¹∧⁼¹↔⁻λζ÷δ⁴»§≔εζ⁰Ｉθ


Try it online! Link is to verbose version of code. 0-indexed. Takes the initial row and column as separate inputs. Explanation:

≔§θηε


Get the row of the chimney at the initial row of the spell.

Ｗη«


Repeat until the spell reaches the top of the chimney.

≔§εζδ


Get the smoke at the current cell.

§≔εζ⁰


Clear the smoke at the current cell.

≦⊖η


Move the spell up one row.

≔§θηε


Get the row of the chimney at the new row of the spell.

ＵＭε⁺κ⎇⁼λζ⁻δ×÷δ⁴№↔Ｅε⁻νζ¹∧⁼¹↔⁻λζ÷δ⁴


Update the row in-place, adjusting for the amount of smoke that gets blown diagonally.

»§≔εζ⁰


Clear the remaining smoke from the chimney.

Ｉθ


Output the final state of the chimney.

# JavaScript (Node.js), 104 bytes

m=>x=>p=g=y=>(P=p>>2,p&=3,r=m[y])&&g(y-1,p=[r[x]+P+P+p],r[x]=0,[x-1,x+1].map(i=>1/r[i]?r[i]+=P:p[0]+=P))


Try it online!

Currying input m, x, y (0-indexed). Output by modify m in-place.

m=> // the input matrix
x=> // the input coordinate "x"
p=  // amount of smoke from row under it
// p is an integer, and could be anything that may be convert to integer
// for example, we initial p as a function so it converted into 0
g=  // recursive function
y=> // the input coordinate "y"
(P=p>>2, // smoke propagate to left / right
p&=3, // p+P+P is the smoke move to middle
r=m[y])&& // whenever the smoke not get out of the chimney
g(y-1, // it propagate to row y-1
p=[r[x]+P+P+p], // with amount p (assuming the smoke can propagate to left and right
r[x]=0, // smoke go away (empty the cell)
[x-1,x+1].map(i=> // for each left / right cell
1/r[i]?r[i]+=P: // if the cell exist, P amount smoke propagate into it
p[0]+=P // otherwise, P amount smoke still leave in middle cell
// which propagate to the next row as described
))