MATLAB/Octave, 115 109 98* bytes
-6 bytes thanks to Luis Mendo
-7 bytes thanks to Luis Mendo
function p=f(A)
B=A;B(:,2:end)=0;for k=1:nnz(A)
B=conv2(B,mod(magic(3),2),'same').*A;end
p=any(B);
Try it online!
(end
keyword is in footer because it's not required when you define the function in a file)
Takes binary array, outputs:
- truthy value as vector full of logical ones
- falsy value as vector having some logical zeros
Such unconsistent falsy was suggested by Luis Mendo and confirmed as valid by as aeh5040.
For consistent true/false logical output replace any(B)
with all(any(B))
.
*for MATLAB it's possible to skim 3 bytes by replacing 'same'
with 's'
.
Ungolfed:
function path = f(A)
B = A; % copy of A
B(:, 2:end) = 0; % zero everything besides 1st column
mask = mod(magic(3),2); % mask for making "steps"
% equal to: [0 1 0
% 1 1 1
% 0 1 0];
for k=1:nnz(A) % max number of necessary steps is amount of 1s in A
% uses 2D convolution of B with m, takes only central part of size of B
B = conv2(B,mask,'same'); % makes "step" in every direction
B = B.*A; % filters only valid steps
end
path = any(B); % check if each column has any value != 0
% if returned vector is full of 1s each column contains nonzero value
% which mean there is a path between both sides
end
Explaination
How 2D convolution works?
If we have array like so:
1 1 0 0 0
0 0 0 1 0
0 0 0 0 0
and a mask
0 1 0
1 1 1
0 1 0
we can imagine convolution of array with mask as taking a mask and placing it on top (so that position of corner is the same) of every cell of array and multiplying it with value of that cell - such operation for one cell gives us one array. And then we sum all of the arrays. In our example:
1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0
0 0 0 0 0 + 0 0 0 0 0 + 0 0 0 1 0 = 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
| | | |
V V V V
0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0
1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 0 1 2 2 1 1 0 0
0 1 0 0 0 0 0 + 0 0 1 0 0 0 0 + 0 0 0 1 1 1 0 = 0 1 1 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Also, in our case because we were using argument 'same'
we were taking only "central" part of result, so because mask was 3x3 we need to cut off sum of 2 columns and 2 rows from the result. To make it even we're cutting first and last rows and are left with:
2 2 1 1 0
1 1 1 1 1
0 0 0 1 0
How we are making "steps"?
Having our input array:
1 1 1 1 0
0 0 0 1 0
0 1 1 1 0
0 1 0 0 0
0 1 1 1 1
We're taking first column:
1 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
then by convolution with our "step" pattern:
0 1 0
1 1 1
0 1 0
we're selecting cells where we could make step from all current/past positions:
1 1 0 0 0
1 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
but since we only can move where 1s are in input array we filter valid positions by multiplying arrays elementwise:
1 1 0 0 0 1 1 1 1 0 1 1 0 0 0
1 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 .* 0 1 1 1 0 = 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 1 0 0 0 0 0
and so we made 1st "step". Then again - convolution to select positions where we can move and filter out result:
1 1 0 0 0 2 2 1 0 0 2 2 1 0 0
0 0 0 0 0 convolution 1 1 0 0 0 multiplication 0 0 0 0 0
0 0 0 0 0 ==> 0 0 0 0 0 ==> 0 0 0 0 0
0 0 0 0 0 steps 0 0 0 0 0 filtering 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Notice we're getting values other than 1, but that doesn't matter - positive numbers will produce only more positive numbers, so we care only if something is 0 or something greater.
So, we continue, next step:
2 2 1 0 0 4 5 3 1 0 4 5 3 1 0
0 0 0 0 0 2 2 1 0 0 0 0 0 0 0
0 0 0 0 0 ==> 0 0 0 0 0 ==> 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
and so on, we continue making steps, finally reaching such state:
15511 26324 29964 27016 0
0 0 0 20240 0
0 3080 6853 12804 0
0 1143 0 0 0
0 340 77 12 1
with 1 in final column, meaning we've reached the right side.