function moves=solver(board);
initboard=board;
moves=[];
k=0;
npegs=sum(sum(board>0));
while k<min(npegs,Inf)
k=k+1;
% % if k==96
% % disp('ok');
% % end
[mvs,raw_vls]=legalmoves(board);
% % if isempty(mv) | vl<0
if isempty(mvs)
k=k-1;
% disp(k,vl)
break
end
vals=raw_vls;
if ~isempty(moves)
lastpeg=moves(end,3:4); chain=find(abs(mvs(:,1)-lastpeg(1))+abs(mvs(:,2)-lastpeg(2))==0);
% % if ~isempty(chain)
% % disp('Oho!')
% % end
vals(chain)=vals(chain)+board(lastpeg(1),lastpeg(2));
vals(chain)=Inf;
end
[nextmv,nextvl]=legalmoves(board,mvs(:,3),mvs(:,4));
if ~isempty(nextmv)
[tf,loc]=ismember(nextmv(:,1:2),mvs(:,3:4),'rows');
vals(loc)=vals(loc)+nextvl;
end
[sort_vals,sort_ind]=sort(vals);
[sort_vals,sort_ind]=deal(flipud(sort_vals),flipud(sort_ind));
mv=mvs(sort_ind(1),:);
vl=sort_vals(1);
moves=[moves;mv];
board=do_moves(board,mv);
end
if isempty(moves)
moves=solver0(board);
return
end
[score,scorevec]=gradeseq(initboard,moves);
% figure;plot(scorevec);
[v,ind]=min(scorevec);
moves=moves(1:ind,:);
function [moves,vals] = legalmoves(board,i,j);
[m,n] = size(board);
% s = @(i,j) sub2ind([m,n],i,j);
if nargin==1
[i,j] = find(board>0);
end
I = [i;i;i;i];
J = [j;j;j;j];
K = [i;i;i-2;i+2];
L = [j-2;j+2;j;j];
h = find(K>0 & K<=m & L>0 & L<=n);
h = h(board(s(size(board),K(h),L(h)))==0 & board(s(size(board),(K(h)+I(h))/2,(L(h)+J(h))/2))>0);
moves = [I(h) J(h) K(h) L(h)];
if isempty(moves)
[moves,vals]=deal([]) ;
return
end
vals=eval_moves(board,moves);
function res=s(vec,i,j);
res=sub2ind(vec,i,j);
% % % [sort_vals,sort_ind]=sort(vals);
% % % [sort_vals,sort_ind]=deal(flipud(sort_vals),flipud(sort_ind));
% % % move=moves(sort_ind(1),:);
% % % val=sort_vals(1);
function res=s(vec,i,j);
res=sub2ind(vec,i,j);
function vals=eval_moves(board,moves);
f=moves(:,[1 2]);
t=moves(:,[3 4]);
over=[mean([f(:,1) t(:,1)],2) mean([f(:,2) t(:,2)],2)];
reward=board(sub2ind(size(board),over(:,1),over(:,2)));
penalty=board(sub2ind(size(board),f(:,1),f(:,2)));
vals=reward-penalty;
function board=do_moves(board,moves)
nmoves=size(moves,1);
for i=1:nmoves
f=moves(i,[1 2]);
t=moves(i,[3 4]);
over=[mean([f(1),t(1)]),mean([f(2),t(2)])];
reward=board(over(1),over(2));
penalty=board(f(1),f(2));
board(t(1),t(2))=board(f(1),f(2));
board(over(1),over(2))=0;
board(f(1),f(2))=0;
end
function moves = solver0(board)
% MOVES = SOLVER(BOARD) Solitaire solver.
%
% MOVES -> [row_from,column_from,row_to,column_to]
%
% The MATLAB Contest Team
% April, 2007
[m,n] = size(board);
% s = @(i,j) sub2ind([m,n],i,j);
[i,j] = find(board>0);
I = [i;i;i;i];
J = [j;j;j;j];
K = [i;i;i-2;i+2];
L = [j-2;j+2;j;j];
h = find(K>0 & K<=m & L>0 & L<=n);
h = h(board(s(size(board),K(h),L(h)))==0 & board(s(size(board),(K(h)+I(h))/2,(L(h)+J(h))/2))>0);
moves = [I(h(1)) J(h(1)) K(h(1)) L(h(1))];
function res=s(vec,i,j);
res=sub2ind(vec,i,j);
function [score,scorevec] = gradeseq(board,moves)
score = sum(board(board(:)>0));
if nargin<2
return
end
[m,n] = size(board);
% tb = @(p) all([p>0 p<=[n m] ~rem(p,1)]);
% % if size(moves,2)~=4 || ~isnumeric(moves) || ~isreal(moves)
% % error('MOVES must be a numeric and real matrix with 4 columns')
% % end
moves = round(moves(1:min(nnz(board>0),end),:));
lastPeg = [-1 -1];
for i = 1:size(moves,1)
f = moves(i,[2 1]);
t = moves(i,[4 3]);
if tb(fliplr(size(board)),f) && board(f(2),f(1))>0 % valid pick
score = score + any(lastPeg-f).*board(f(2),f(1));
lastPeg = f;
mp = (f+t)/2;
if tb(fliplr(size(board)),t) && board(t(2),t(1))==0 && all(sort(abs(f-t))==[0 2]) ...
&& board(mp(2),mp(1))>0 % valid move
lastPeg = t;
score = score - board(mp(2),mp(1));
board(t(2),t(1)) = board(f(2),f(1));
board([f(2) mp(2)],[f(1) mp(1)]) = 0;
end
else
lastPeg = [0 0];
end
scorevec(i)=score;
end
function res=tb(vec,p);
res=all([p>0 p<=vec ~rem(p,1)]);
|