Is it L-convex?
Matlab, 182 bytes
Idea: Repeat for every 1
in the polyomino matrix:
- Create new matrix with only the given
1
but the rest zero. - for every
1
in this new matrix (repeat until nothing changes anymore)- add
1
as neighbours in x direction if there are1
as neighbours in the polynomio
- add
- for every
1
in this new matrix (repeat until nothing changes anymore)- add
1
as neighbours in x direction if there are1
as neighbours in the polynomio
- add
Now 1
in the new matrix should cover all 1
in the polynomio-matrix that are reachable from the given starting point by first going in x-direction and then in y-direction. Now we can repeat the same process but with first going into y-direction and then in x-direction. Now every 1
of the polyomino matrix should be reached at once or both times. If not, then we have found a position in the polynomio matrix that cannot be reached from every other position by an L
-path.
Golfed:
function r=f(a);[i,j,b]=find(a);N=nnz(i);r=1;for k=1:N;K=1:3;for l=1:2;c=b;b=a*0;b(i(k),j(k))=1;for z=1:2*N; b=conv2(b+0,K,'s')&a;if z==N;K=K';end;end;end;r=r*all(b(:)|c(:)>=a(:));end
With comments:
function r=codegolf_L_convex(a);
%a=[0,1;1,1];
[i,j,b]=find(a);%b just needs to be initialized, does not really mattter
N=nnz(i);%number of ones in the matrix
r=1;%return value
for k=1:N;%go throu all '1' in the matrix
%expand that pixel in x dir:
K=1:3;%convolution kernel (just three positive values needed)
for l=1:2;%first horizontal->vertical then vertical->horizontal
c=b;%backup for considering both runs
b=a*0;
b(i(k),j(k))=1; %set the seed
for z=1:2*N;
b=conv2(b+0,K,'s')&a; %expand the seed horizontally (or vertically for the second half) but only within the polyomino
if z==N;
K=K'; %change horizontal/vertical
end;
end;
end;
r=r*all(b(:)|c(:)>=a(:));%check whether we can really reach every point
end
Test cases script:
disp('all false -------------');
a=[0,1;1,0];
f(a)
a=[1,1,1;1,0,1;1,1,1];
f(a)
a=[1,1,0,1;1,1,1,1;1,1,1,0];
f(a)
a=[1,1,0,0;1,0,0,0;0,0,1,1];
f(a)
a=[0,1,1,0,0;1,1,1,1,0;0,1,1,1,0;0,0,1,1,0];
f(a)
a=[0,1,1,0,0,0;0,1,1,1,1,0;0,0,1,1,1,1];
f(a)
disp('all true +++++++++++++');
a=[1];
f(a)
a=[0,1;1,1];
f(a)
a=[0,1,0;1,1,1;0,1,0];
f(a)
a=[0,0,1;0,1,1;1,1,1];
f(a)
a=[1,1,1,0,0;1,1,1,1,0;0,1,1,0,0;0,1,0,0,0];
f(a)
a=[0,1,1,0,0,0;0,1,1,0,0,0;1,1,1,1,0,0;1,1,1,1,1,1;0,0,1,0,0,0];
f(a)
Snails, 45 24
&
!{\1t\1!{o\1,nf\1,!.!~
Right after posting my initial solution, I realized there was a much better way. The original program traveled around the square formed by the paths between two 1
s, testing for the presence of a 0 in each pair of sides. It also had to have a special case for straight line paths. The new version starts by teleporting from one 1
to the other, and testing for the absence of a straight or L-shaped path of 1
s back to the start.
Mathematica, 129 127 bytes
3>GraphDiameter@Graph[#,#<->#2&@@@Select[#~Tuples~2,!FreeQ[#-#2&@@#,0]&]]&@Position[#,1]&&{#,Thread@#}~FreeQ~{___,1,0..,1,___}&
Explanation:
First, if there is a 0
between two 1
s on the same row or column, the array is not L-convex, because we can't connect the two 1
s.
After excluding this case, every two 1
s on the same row or column can be connected by a straight path. We can generate a graph, whose vertices are the positions of 1
s in the array, and edges are pairs of 1
s on the same row or column. Then the array is L-convex if and only if the diameter of the graph is less than 3.