| Code: | function W = solver(B)
W = zeros(0,4);
[r,c]=size(B); % Size of the board
numbers=unique(B); % Numbers in the board
for i=length(numbers):-1:2 % Every number
[r1,c1]=find(B==numbers(i)); % Positions of current number
if size(r1,1)==1
numbers(end)=[];
continue;
end
[rbad,cbad]=find(xor(B>0,B==numbers(i))); % Banned positions;
rbad=[rbad;W(:,1)]; % First approach. Lines banned
cbad=[cbad;W(:,2)]; % First approach. Lines banned
cpos=[r1(1),c1(1)]; % Current position
W1=line(r,c,r1(2),c1(2),rbad,cbad,cpos);
W=[W;W1];
end
if isempty(W)
W = zeros(0,4);
end
function W=line(r,c,r1,c1,rbad,cbad,cpos)
W = zeros(0,4);
nonmoved=[];
while sum(cpos==[r1,c1])<2
moves=findmoves(r,c,cpos(1),cpos(2),rbad,cbad,r1,c1);
if isempty(moves) % no possible movements from current position
if isempty(nonmoved),
if ~isempty(W)
W=[];
end
break;
end
while size(W,1)~=nonmoved(end,3)
cpos=W(end,1:2);
W(end,:)=[];
end
rbad(end+1)=cpos(1);
cbad(end+1)=cpos(2);
W(end+1,:)=[cpos nonmoved(end,1:2)];
cpos=nonmoved(end,1:2);
nonmoved(end,:)=[];
elseif size(moves,1)==1, % Mandatory movement
rbad(end+1)=cpos(1);
cbad(end+1)=cpos(2);
W(end+1,:)=[cpos moves(1,:)];
cpos=moves(1,:);
else % Several posibilities
nonmoved(end+[1:(size(moves,1)-1)],:)=[moves(2:end,:) ...
ones((size(moves,1)-1),1)*size(W,1)];
rbad(end+1)=cpos(1);
cbad(end+1)=cpos(2);
W(end+1,:)=[cpos moves(1,:)];
cpos=moves(1,:);
end
aa=find(sum(abs([cpos(1)-W(:,1) cpos(2)-W(:,2)]),2)==1);
if length(aa)>1,
arround=aa;
W((arround(1)+1):end,:)=[];
W(end,3:4)=cpos;
if ~isempty(nonmoved)
nonmoved(nonmoved(:,3)>=size(W,1),:)=[];
if ~isempty(nonmoved)&nonmoved(end,1:2)==cpos
nonmoved(end,:)=[];
end
end
end
end
% Find possible movements from current position;
function moves=findmoves(r,c,r1,c1,rbad,cbad,r2,c2)
rr=r2-r1;
cc=c2-c1;
% Preferred direction of the movements.
if rr>0
if cc>0
if abs(rr)>abs(cc)
inc=[1 0;0 1;0 -1;-1 0];
else
inc=[0 1;1 0;-1 0;0 -1];
end
else
if abs(rr)>abs(cc)
inc=[1 0;0 -1;0 1;-1 0];
else
inc=[0 -1;1 0;-1 0;0 1];
end
end
else
if cc>0
if abs(rr)>abs(cc)
inc=[-1 0;0 1;0 -1;1 0];
else
inc=[0 1;-1 0;1 0;0 -1];
end
else
if abs(rr)>abs(cc)
inc=[-1 0;0 -1;0 1;1 0];
else
inc=[0 -1;-1 0;1 0;0 1];
end
end
end
moves=ones(4,1)*[r1 c1]+inc;
moves=moves(~sum([moves<ones(4,2)|moves>ones(4,1)*[r c]]'),:);
for i=size(moves,1):-1:1,
if sum(moves(i,1)==rbad & moves(i,2)==cbad)
moves(i,:)=[];
end
end
|