Winner Yi Cao (Buy a ticket)

Finish 2007-05-16 12:00:00 UTC

locke5_Inf_2_faster1_oof

by eigenvector

Status: Passed
Results: 43162.55 (cyc: 9)
CPU Time: 84.0106
Score: 4449.7
Submitted at: 2007-05-12 19:14:38 UTC
Scored at: 2007-05-12 19:16:52 UTC

Current Rank: 2359th
Based on: locke5_Inf_2_faster1 (diff)
Basis for: locke5_Inf_2_faster1_precise (diff)

Comments
Please login or create a profile.
Code
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)]);