function [message,result,solverTime] = runcontest(flagVisualize,whichBoards)
%RUNCONTEST Test an entry.
% [MESSAGE,RESULTS,TIME] = RUNCONTEST runs the file solver.m against all
% the problems defined in testsuite_sample.mat. 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 the answer.
%
% RUNCONTEST(true) graphically visualize the results.
%
% RUNCONTEST(true/false, DOBOARDS) runs the file solver.m against the
% problems enumerated in the vector DOBOARDS as defined in the testsuite.
% Copyright 2010 The MathWorks, Inc.
% The MATLAB Contest Team
% November, 2010
testSuiteFile = 'testsuite_sample.mat';
load(testSuiteFile,'testsuite')
% Argument parsing.
if (nargin<2)
whichBoards = 1:numel(testsuite); % do all boards in test suite
end
if (nargin < 1)
flagVisualize = 0;
end
numBoards = numel(whichBoards);
solverTime = zeros(numBoards,1);
solverScore = zeros(numBoards,1);
if flagVisualize
fh = figure;
end
for i = 1:numBoards
[chart, aIndex, bIndex, maxThrottle] = getboard(testsuite,whichBoards(i));
if flagVisualize
visualize(chart,aIndex,bIndex,fh)
fprintf('Board number %d :\n',whichBoards(i))
fprintf(' wR wC tR tC vRf vCf Rf Cf \n')
end
time0 = cputime;
[thrustRow, thrustCol] = solver(chart, aIndex, bIndex, maxThrottle);
solverTime(i) = cputime-time0;
[thrustRow, thrustCol] = validatesolution(thrustRow, thrustCol, maxThrottle);
[dA,dB] = runsolution(thrustRow, thrustCol, chart, aIndex, bIndex, flagVisualize);
solverScore(i) = scoresolution(dA,dB,thrustRow,thrustCol);
if flagVisualize
fprintf(' Score: %d \n\n',solverScore(i))
if i<numBoards
if mypause(fh)
break; % stop
end
end
end
end
% Report results.
result = sum(solverScore);
resultTime = sum(solverTime);
message = sprintf('results: %.2f\ntime: %.2f', result, resultTime);
end
function [thrustRow, thrustCol] = validatesolution(thrustRow, thrustCol, maxThrottle)
% VALIDATESOLUTION Validates the solution vectors given by the solver
% Ensure column vectors and reals
thrustRow = real(thrustRow(:));
thrustCol = real(thrustCol(:));
% Check maximum number of moves
mnmoves = 1000;
if numel(thrustRow) > mnmoves
thrustRow = thrustRow(1:mnmoves);
end
if numel(thrustCol) > mnmoves
thrustCol = thrustCol(1:mnmoves);
end
% Ensure integers
if any(rem(thrustRow,1))
thrustRow = round(thrustRow);
end
if any(rem(thrustCol,1))
thrustCol = round(thrustCol);
end
% Ensure same length
ntR = numel(thrustRow);
ntC = numel(thrustCol);
if ntR~=ntC
n = min(ntR,ntC);
thrustRow = thrustRow(1:n);
thrustCol = thrustCol(1:n);
end
% Check maximum throttle
h = (abs(thrustRow) + abs(thrustCol)) > maxThrottle;
if any(h)
% Motor is blown for every turn the throttle exceeds the motor capacity!
thrustRow(h) = 0;
thrustCol(h) = 0;
end
end
function [dA, dB] = runsolution(thrustRow, thrustCol, chart, aIndex, bIndex, flagVisualize)
% RUNSOLUTION Simulates the navigation trajectory given the winds and the
% motor thrust.
rowWind = chart(:,:,1);
colWind = chart(:,:,2);
[nR,nC] = size(rowWind);
[AR,AC] = ind2sub([nR,nC],aIndex);
[BR,BC] = ind2sub([nR,nC],bIndex);
% Initialize variables at start point (A)
fR = AR; fC =AC;
fvR = 0; fvC = 0;
dB = (fR-BR)^2 + (fC-BC)^2;
for i = 1:numel(thrustRow)
ivR = fvR + thrustRow(i) + rowWind(fR,fC);
ivC = fvC + thrustCol(i) + colWind(fR,fC);
iR = fR + ivR;
iC = fC + ivC;
if iR>nR || iR<1 || iC>nC || iC<1
break % out of bounds
end
if flagVisualize
plot([fC iC],[fR iR],'r-')
plot(iC,iR,'ro','MarkerFaceColor','r')
fprintf(' %4d %4d %4d %4d %4d %4d %4d %4d\n',...
rowWind(fR,fC),colWind(fR,fC),thrustRow(i),thrustCol(i),ivR,ivC,iR,iC)
end
fR = iR;
fC = iC;
fvR = ivR;
fvC = ivC;
% Verify if this is the closest point to B
if ((fR-BR)^2 + (fC-BC)^2) < dB
dB = (fR-BR)^2 + (fC-BC)^2;
end
end
dA = (fR-AR)^2 + (fC-AC)^2; % Final distance to A
end
function score = scoresolution(dA,dB,thrustRow,thrustCol)
% SCORESOLUTION Calculates the score for the solution.
score = dB + dA + sum(abs(thrustRow)) + sum(abs(thrustCol));
end
function [chart, aIndex, bIndex, maxThrottle] = getboard(testsuite,i)
% GETBOARD Gets the i-th problem from the loaded testsuite
i = round(min(max(1,i),numel(testsuite)));
chart = testsuite(i).chart;
aIndex = testsuite(i).aIndex;
bIndex = testsuite(i).bIndex;
maxThrottle = testsuite(i).maxThrottle;
end
function visualize(chart,aIndex,bIndex,fh)
% VISUALIZE draws the board in a figure window indicating the wind, the
% start position and the target position.
colWind = chart(:,:,1);
rowWind = chart(:,:,2);
[nR,nC] = size(colWind);
% Sets the figure
figure(fh)
clf
set(fh,'color',[1 1 1]);
% Sets the axes
cla
axis equal
set(gca,'Ydir','reverse')
hold on
box off
axis([0 nC 0 nR]+.5)
set(gca,'xtick',1:nC)
set(gca,'ytick',1:nR)
% Draws the blue grid (the sea)
for i = 1:nR
for j = 1:nC
rectangle('Position', [j-.5,i-.5,1,1],'linewidth',3,'EdgeColor',[.8 .9 1])
end
end
% Draws the start position and the target position
[Ri,Ci] = ind2sub([nR,nC],aIndex);
rectangle('Position', [Ci-.45,Ri-.45,.9,.9], 'Curvature',[.7 .7],'FaceColor',...
[.8 1 .8],'EdgeColor',[0 .7 0])
[Ri,Ci] = ind2sub([nR,nC],bIndex);
rectangle('Position', [Ci-.45,Ri-.45,.9,.9], 'Curvature',[.7 .7],'FaceColor',...
[1 .8 .8],'EdgeColor',[1 0 0])
% Draw the arrows for the wind
for i = 1:nR
for j = 1:nC
wind = rowWind(i,j);
d = sign(wind);
n = abs(wind);
for k = 1:n
patch(j+[-.3 .3 .2 .2 .3].*d,i+[0 0 -.05 .05 0]-.3+(k).*.6/(n+1),...
[.7 .7 .7],'EdgeColor',[.7 .7 .7])
end
wind = colWind(i,j);
d = sign(wind);
n = abs(wind);
for k = 1:n
patch(j+[0 0 -.05 .05 0]-.3+(k).*.6/(n+1),i+[-.3 .3 .2 .2 .3].*d,...
[.7 .7 .7],'EdgeColor',[.7 .7 .7])
end
end
end
end
function flag = mypause(fh)
% Implements an uicontrol to pasuse and resume the simulation
flag = false;
h1 = uicontrol('Position', [20 5 100 20], 'String', 'Next Problem', ...
'Callback', 'uiresume(gcbf)');
h2 = uicontrol('Position', [140 5 100 20], 'String', 'Stop', ...
'Callback', 'set(gcbo,''userdata'',1);uiresume(gcbf)');
uiwait(fh);
if ishandle(h1)
delete(h1);
end
if ishandle(h2)
flag = ~isempty(get(h2,'userdata')); % stop?
delete(h2);
end
end