local base = {
{0, 0, 0, 0, 0},
{0, 1, 1, 1, 0},
{0, 0, 0, 1, 0},
{0, 0, 0, 1, 0},
{0, 0, 0, 1, 0},
}
local filter = {
{1, 0, 1},
{0, 1, 0},
{1, 0, 1},
}
-- You can have etc. 5 x 3 filters mapped on 7 x 9 matrices.
local output = {}
-- Filter column & row fitting / check how many placements can be made.
local matrix_fitting_y = (#base - #filter) + 1 -- +1 for first placement & fit in column
local matrix_fitting_x = (#base[1] - #filter[1]) + 1 -- -||- fit in row
-- Construct size of output
for output_tbls = 1, matrix_fitting_y do
table.insert(output, {})
for output_vals = 1, matrix_fitting_x do
table.insert(output[output_tbls], 0)
end
end
-- Per output y and x, we calculate the y, x index of filter toward base & sum it into output.
for mxf_y = 1, matrix_fitting_y do
for mxf_x = 1, matrix_fitting_x do
for y = 1, #filter do
for x = 1, #filter[1] do
local calc = base[(mxf_y + y)-1][(mxf_x + x)-1] * filter[y][x]
if calc >= 1 then
output[mxf_y][mxf_x] += calc
end
end
end
end
end
print(output)
Here you go. It works with a larger base matrix too and will appropriately create the size of the output based on how many filter size iterations can fit in it.
I’m sure you can code golf it for better performance.
Here are some outputs of your 5x5 base with the 3x3 filter:
Here is one with a 6 x 6 base with the same 3 x 3 filter seen in my script that I sent:
You can also create a larger filter and it will automatically calculate the output size for it.
How did I approach this problem?
I first made the same system @Soliform had but then I realized that the base and filter can be larger than that, so it won’t work and the output has to grow along with how many iterations it calculated.
So I realized that you can try to calculate how many times your first row can fit on top of the first row (I first approached it from a 1 dimensional perspective):
{0, 1, 0, 1, 0, 1, 0}
{1, 0, 1}
Say your first row is 7 blocks long, how many 3 blocks can fit by jumping by 1 each iteration? I kept my eye on the first index of the filter. How many times can that first index stay inside the 7 blocks without having the entire row go out of bounds? If you take 7 - 3 you get 4 times right? But if you calculate it, you’ll see that you could do it 5 times. This is because the first placement isn’t counted, we’re always adding by 1 from the beginning of our calculation, so add 1. That’s how I got my matrix_fitting. Now if you take a larger filter you’ll see that this logic will now apply to it perfectly.
matrix_fitting = (#base - #filter) + 1
Now we can use this fitting to calculate the output. So in this example I’m talking about, (7 - 3) + 1 = 5, so we construct a 5 x 5 output and fill it with empty values.
Now we calculate the possible fittings in the base Y, and loop X inside. X always jumps N amount of times (matrix_fitting times) each Y iteration so the X for loop goes inside Y obviously.
Now inside this base matrix X loop, we can start our filter matrix calculation, looping through X within Y the length of the filter.
So now all we do is make a new fitting, take the position in the base and calculate the y and x on top of it respectively to get the position of where the filters current index is in the base - 1 due to index problem caused by for loops starting at 1.
if base[(mxf_y + y)-1][(mxf_x + x)-1] * filter[y][x] >= 1 then
Now we calculate the value of the fittings value that got returned against our filters value which it is currently on and multiplies it. If it returns 1 or greater (which it would if you have 2’s or something), then we can simply take the position of the output and add 1 to it. If the loop finds another 1 in the current frame, it adds another +1 to that very same output index value.
(Btw if you want to check if the filter is greater than the base it’ll be super easy: If the matrix_fitting is below 0)
When the loop is done, we can output the matrix!
EDIT:
Edited the code so you can now have non equal sided matrices like for example a base matrix: 9 x 7 which gets mapped on etc 3 x 5 filters!
EDIT V2:
Now if you have values higher than 1 in either the base or the filter, the output will appropriately calculate the sum.