Finish 2010-11-17 12:00:00 UTC

SPLF 5

by Daniel E

Status: Passed
Results: 17920 (cyc: 8, node: 1408)
CPU Time: 14.163
Score: 3585.44
Submitted at: 2010-11-12 16:07:06 UTC
Scored at: 2010-11-12 16:09:34 UTC

Current Rank: 2127th (Highest: 60th )
Based on: SPLF 4 (diff)

Comments
Please login or create a profile.
Code
function [bestRow, bestCol] = solver(chart, aIndex, bIndex, maxThrottle)

[rows, cols, unused] = size(chart);

aRow = mod(aIndex - 1, rows) + 1;
aCol = floor((aIndex - 1) / rows) + 1;
bRow = mod(bIndex - 1, rows) + 1;
bCol = floor((bIndex - 1) / rows) + 1;

[allThrustRow, allThrustCol] = getAllThrusts(maxThrottle);

[initThrustRow,   initThrustCol, history] = thrustToPos(chart,             0,             0, aRow, aCol, bRow, bCol, allThrustRow, allThrustCol, maxThrottle, false);

highScore = inf;
for n=1:size(history, 1)
    [finalThrustRow, finalThrustCol     ] = thrustToPos(chart, history(n, 3), history(n, 4), history(n, 1), history(n, 2), aRow, aCol, allThrustRow, allThrustCol, maxThrottle, true);

    thrustRow = [initThrustRow(1:n) finalThrustRow];
    thrustCol = [initThrustCol(1:n) finalThrustCol];
    [thrustRow thrustCol score] = pruneBasedOnScore(chart, aIndex, bIndex, thrustRow, thrustCol);
    if score < highScore
        highScore = score;
        bestRow = thrustRow;
        bestCol = thrustCol;
    end
end


function [thrustRowVec, thrustColVec, history] = thrustToPos(chart, velRow, velCol, startRow, startCol, endRow, endCol, allThrustRow, allThrustCol, maxThrust, allowDeadNextMove)

history = [];
thrustRowVec = [];
thrustColVec = [];
iterations = 1;
while ~isempty(startRow) && (startRow ~= endRow || startCol ~= endCol) && iterations < 100
    [thrustRow, thrustCol, newVelRow, newVelCol, newStartRow, newStartCol] = aimFor(chart, velRow, velCol, startRow, startCol, endRow, endCol, allThrustRow, allThrustCol, maxThrust, allowDeadNextMove, history);
    if isempty(newStartRow)
        break
    end
    velRow = newVelRow;
    velCol = newVelCol;
    startRow = newStartRow;
    startCol = newStartCol;
    history = [history; startRow startCol velRow velCol];
    thrustRowVec = [thrustRowVec thrustRow];
    thrustColVec = [thrustColVec thrustCol];
    iterations = iterations + 1;
end

function [thrustRow, thrustCol] = getAllThrusts(maxThrottle)

elems = 2 * (maxThrottle ^ 2 + maxThrottle) + 1;
thrustRow = zeros(elems, 1);
thrustCol = zeros(elems, 1);
i = 1;
for r = -maxThrottle:maxThrottle
    maxcThrottle = maxThrottle - abs(r);
    c = -maxcThrottle:maxcThrottle;
    j = i + length(c) - 1;
    thrustCol(i:j) = c;
    thrustRow(i:j) = r;
    i = j + 1;
end

function [thrustRow, thrustCol, velRow, velCol, posRow, posCol] = aimFor(chart, initVelRow, initVelCol, startRow, startCol, endRow, endCol, allThrustRow, allThrustCol, maxThrust, allowDeadNextMove, history)

[velRow, velCol, posRow, posCol] = applyThrust(chart, initVelRow, initVelCol, startRow, startCol, allThrustRow, allThrustCol);
invalid = posRow < 1 | posRow > size(chart, 1) | posCol < 1 | posCol > size(chart, 2);

velRow(invalid) = [];
velCol(invalid) = [];
allThrustRow(invalid) = [];
allThrustCol(invalid) = [];
posRow(invalid) = [];
posCol(invalid) = [];
inertiaRow = [];
inertiaCol = [];

if ~allowDeadNextMove || ~any(posRow == endRow & posCol == endCol)
    windRow = chart(sub2ind(size(chart), posRow, posCol, ones(size(posRow))));
    windCol = chart(sub2ind(size(chart), posRow, posCol, 2 * ones(size(posRow))));
    inertiaRow = posRow + velRow + windRow;
    inertiaCol = posCol + velCol + windCol;
    thrustRequiredToNotDie = max(1 - inertiaRow, 0) + max(inertiaRow - size(chart, 1), 0) + ...
                             max(1 - inertiaCol, 0) + max(inertiaCol - size(chart, 2) , 0);

    invalid = thrustRequiredToNotDie > maxThrust;

    if ~all(invalid)
        velRow(invalid) = [];
        velCol(invalid) = [];
        allThrustRow(invalid) = [];
        allThrustCol(invalid) = [];
        posRow(invalid) = [];
        posCol(invalid) = [];
        windRow(invalid) = [];
        windCol(invalid) = [];
        inertiaRow(invalid) = [];
        inertiaCol(invalid) = [];
    end

    if ~isempty(velRow)
        if all(abs(velRow + windRow) + abs(velCol + windCol) > maxThrust)
            maxThrust = min(abs(velRow + windRow) + abs(velCol + windCol));
        end

        invalid = abs(velRow + windRow) + abs(velCol + windCol) > maxThrust;

        if ~all(invalid)
            velRow(invalid) = [];
            velCol(invalid) = [];
            allThrustRow(invalid) = [];
            allThrustCol(invalid) = [];
            posRow(invalid) = [];
            posCol(invalid) = [];
            inertiaRow(invalid) = [];
            inertiaCol(invalid) = [];
        end
    end
else
    inertiaRow = zeros(size(posRow));
    inertiaCol = zeros(size(posRow));
end

distance = (endRow - posRow) .^ 2 + (endCol - posCol) .^ 2;
distance2 = (endRow - inertiaRow) .^ 2 + (endCol - inertiaCol) .^ 2;
distance = min(distance, distance2);
cost = (abs(allThrustRow) + abs(allThrustCol));
minDistance = min(distance);
minIndex = find(distance == minDistance);
[minCost, minCostIndex] = min(cost(minIndex));
minIndex = minIndex(minCostIndex);
thrustRow = allThrustRow(minIndex);
thrustCol = allThrustCol(minIndex);
velRow = velRow(minIndex);
velCol = velCol(minIndex);
posRow = posRow(minIndex);
posCol = posCol(minIndex);

repeatedPosVel = intersect([posRow posCol velRow velCol], history, 'rows');
if ~isempty(repeatedPosVel)
    thrustRow = [];
    thrustCol = [];
    velRow = [];
    velCol = [];
    posRow = [];
    posCol = [];
end

function [velRow, velCol, posRow, posCol] = applyThrust(chart, initVelRow, initVelCol, startRow, startCol, thrustRow, thrustCol)

velRow = initVelRow + thrustRow + chart(startRow, startCol, 1);
velCol = initVelCol + thrustCol + chart(startRow, startCol, 2);

posRow = startRow + velRow;
posCol = startCol + velCol;

function [thrustRow thrustCol highScore] = pruneBasedOnScore(chart, aIndex, bIndex, thrustRow, thrustCol)

highScore = inf;
index = inf;
for n=0:length(thrustRow)
    [dA, dB] = runsolution(thrustRow(1:n), thrustCol(1:n), chart, aIndex, bIndex);
    score = scoresolution(dA,dB,thrustRow(1:n),thrustCol(1:n));
    if score < highScore
        highScore = score;
        index = n;
    end
end
thrustRow = thrustRow(1:index);
thrustCol = thrustCol(1:index);

function [dA, dB] = runsolution(thrustRow, thrustCol, chart, aIndex, bIndex)

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
    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

function score = scoresolution(dA,dB,thrustRow,thrustCol)

score = dB + dA + sum(abs(thrustRow)) + sum(abs(thrustCol));