function [message,results,timeElapsed] = runcontest(drawboard)
%RUNCONTEST Test an entry in the furniture moving contest.
% [MESSAGE,RESULTS,TIME] = RUNCONTEST(DRAWBOARD) runs the M-file
% solver.m against all the problems defined in testsuite_sample.mat. The
% input DRAWBOARD specifies if you want to graphically visualize the results.
% MESSAGE returns a summary of the testing. RESULTS measures how well the
% entry solved the problem, and TIME measures the time the entry took to
% compute its answer.
%
% Copyright 2004 The MathWorks, Inc.
if (nargin < 1)
drawboard = 0;
end
% Load the testsuite
load testsuite_sample testsuite
% Run the submission for each problem in the suite.
score = 0;
n = length(testsuite);
moves = cell(n);
clear global
timeElapsed = 0;
for k = 1:n
if drawboard
viewsolution(testsuite(k).ai,testsuite(k).af)
end
time0 = cputime;
moves{k} = solver(testsuite(k).ai,testsuite(k).af,testsuite(k).w);
timeElapsed = timeElapsed+cputime-time0;
clear global
if drawboard
score(k) = grade(testsuite(k).ai,testsuite(k).af,testsuite(k).w,moves{k});
viewsolution(testsuite(k).ai,testsuite(k).af,moves{k})
end
end
% Check and score each answer.
if ~drawboard
for k = 1:n
score(k) = grade(testsuite(k).ai,testsuite(k).af,testsuite(k).w,moves{k});
end
end
% Report results.
results = sum(score);
message = sprintf('%.0f units of work, %.1f seconds',results,timeElapsed);
%===============================================================================
function score = grade(ai,af,w,mv)
%GRADE Make sure the answer is valid and compute its score.
% N=1, E=2, S=3, W=4
I = [0 1 0 -1];
J = [1 0 -1 0];
% First column of moves should be integer values from 1 to N
if any(round(mv(:,1)) ~= mv(:,1)) || any(mv(:,1) < 1) || any(mv(:,1) > length(w))
error('Only block numbers from 1 to the number of blocks are allowed');
end
% Second column of moves should be integer values from 1 to 4
if any(round(mv(:,2)) ~= mv(:,2)) || any(mv(:,2) < 1) || any(mv(:,2) > 4)
error('Only directional specifications from 1 to 4 are allowed');
end
% Step through the moves and make sure there are no illegal moves and
% verify that the final location is the specified location
a = ai;
for k = 1:size(mv,1)
[row, col] = find(a==mv(k,1));
a(row,col) = 0;
% new position of the block
row = row + I(mv(k,2));
col = col + J(mv(k,2));
% check edges
if (row < 1) || (col < 1) || (row > size(a,1)) || (col > size(a,2))
error('A move resulted in a piece of furniture moving off of the grid');
end
% check collisions
if (a(row,col) ~= 0)
error('A move resulted in a collision');
end
% place the block in the new position
a(row, col) = mv(k,1);
end
% Make sure we end up in the correct location
if any(a(:)~=af(:))
error('The furniture did not all end up in the correct location');
end
% compute the score
score = sum(w(mv(:,1)));
%===============================================================================
function viewsolution(ai,af,mv)
% N=1, E=2, S=3, W=4
I = [0 1 0 -1];
J = [1 0 -1 0];
[m,n] = size(ai);
clf
set(gcf,'DoubleBuffer','on')
% Display before and after images
colormap([1 1 1;jet(max(ai(:)))]);
subplot(3,1,1)
image(ai+1)
title('Initial block locations')
axis equal
axis([0 n 0 m]+.5)
set(gca,'XTick',[],'YTick',[])
subplot(3,1,2)
image(af+1)
title('Final block locations')
axis equal
axis([0 n 0 m]+.5)
set(gca,'XTick',[],'YTick',[])
% Display solution.
subplot(3,1,3); h = image(ai+1); ; title('Solution');
axis equal
axis([0 n 0 m]+.5)
set(gca,'XTick',[],'YTick',[])
drawnow
% Animate the solution.
if (nargin > 2)
a = ai;
for n = 1:size(mv,1)
bid = mv(n,1);
[i,j] = find(a==bid);
r = mv(n,2);
ni = i + I(r);
nj = j + J(r);
a(ni,nj) = bid;
a(i,j) = 0;
set(h,'CData',a+1)
pause(.02)
end
set(gcf,'ToolBar','figure')
u = uicontrol('String','Next','callback','uiresume(gcf)');
uiwait(gcf)
delete(u)
end