Image Smoother
Problem
Apply a 3×3 box blur, taking the floored mean of each cell's neighborhood (clipped at edges).
img=[[1,1,1],[1,0,1],[1,1,1]][[0,0,0],[0,0,0],[0,0,0]]def image_smoother(img):
m, n = len(img), len(img[0])
out = [[0] * n for _ in range(m)]
for r in range(m):
for c in range(n):
s = k = 0
for dr in (-1, 0, 1):
for dc in (-1, 0, 1):
rr, cc = r + dr, c + dc
if 0 <= rr < m and 0 <= cc < n: s += img[rr][cc]; k += 1
out[r][c] = s // k
return out
function imageSmoother(img) {
const m = img.length, n = img[0].length;
const out = Array.from({length: m}, () => new Array(n).fill(0));
for (let r = 0; r < m; r++)
for (let c = 0; c < n; c++) {
let s = 0, k = 0;
for (let dr = -1; dr <= 1; dr++) for (let dc = -1; dc <= 1; dc++) {
const rr = r + dr, cc = c + dc;
if (rr >= 0 && rr < m && cc >= 0 && cc < n) { s += img[rr][cc]; k++; }
}
out[r][c] = Math.floor(s / k);
}
return out;
}
int[][] imageSmoother(int[][] img) {
int m = img.length, n = img[0].length;
int[][] out = new int[m][n];
for (int r = 0; r < m; r++) for (int c = 0; c < n; c++) {
int s = 0, k = 0;
for (int dr = -1; dr <= 1; dr++) for (int dc = -1; dc <= 1; dc++) {
int rr = r + dr, cc = c + dc;
if (rr >= 0 && rr < m && cc >= 0 && cc < n) { s += img[rr][cc]; k++; }
}
out[r][c] = s / k;
}
return out;
}
vector> imageSmoother(vector>& img) {
int m = img.size(), n = img[0].size();
vector> out(m, vector(n));
for (int r = 0; r < m; r++) for (int c = 0; c < n; c++) {
int s = 0, k = 0;
for (int dr = -1; dr <= 1; dr++) for (int dc = -1; dc <= 1; dc++) {
int rr = r + dr, cc = c + dc;
if (rr >= 0 && rr < m && cc >= 0 && cc < n) { s += img[rr][cc]; k++; }
}
out[r][c] = s / k;
}
return out;
}
Explanation
This is a classic box blur: each output cell becomes the rounded-down average of itself and its neighbors in a 3x3 window. The only twist is that cells near the edges have fewer than 9 neighbors, so we must average only the ones that actually exist.
We create a fresh out grid so that the smoothing uses the original values, never partially-updated ones. For every cell (r, c) we look at the offsets dr, dc ranging over -1, 0, 1 in both directions, which visits the cell and up to its 8 neighbors.
For each neighbor that lies inside the grid we add its value to a sum s and increment a counter k. The output is s // k (integer division), which floors the mean. Dividing by k rather than always by 9 is what correctly handles corners and edges.
Example: top-left cell of [[1,1,1],[1,0,1],[1,1,1]] only has 4 cells in its window (1, 1, 1, 0), so its average is 3 // 4 = 0. The center cell sees all 9 values summing to 8, giving 8 // 9 = 0. Every cell ends up 0.
Each cell does a constant amount of work (at most 9 lookups), so the total time is proportional to the grid size.