ID:46041
Title:a long hmmmm....
Author:Matt Butts
Date:2008-05-01 21:32:35
Score:20917.8090
Result:208669.00 (cyc: 54, node: 2702)
CPU Time:11.1539
Status:Passed
Comments:
Based on:none
Code:
function W = solver(B)

W = zeros(0,4);
% find all pins
values = unique(B);
% find number of pins
for pin = 2:length(values)
    pins(pin-1).value = values(pin);
    [pins(pin-1).rows,pins(pin-1).cols] = find(B==pins(pin-1).value);
    pins(pin-1).num = length(pins(pin-1).rows);
end

[c,index]=min(cost(B,pins)');
workB = B;

while c < inf    
    current_pin.rows = pins(index).rows;
    current_pin.cols = pins(index).cols;
    solder.rows = [];
    solder.cols = [];
    
    % find a good starting point...
    start.rows = sum(current_pin.rows)/length(current_pin.rows);
    start.cols = sum(current_pin.cols)/length(current_pin.cols);
    [junk first] = findShortestPath(start,current_pin);
    startIndex=intersect(find(current_pin.rows==first(1)),find(current_pin.cols==first(2)));
    solder.rows(length(solder.rows)+1)=current_pin.rows(startIndex);
    solder.cols(length(solder.cols)+1)=current_pin.cols(startIndex);
    current_pin.rows = rmrow(current_pin.rows,startIndex);
    current_pin.cols = rmrow(current_pin.cols,startIndex);
    num = 1;
    while num < pins(index).num
        [from to] = findShortestPath(solder,current_pin);
        [newMoves, workB_, solder_, connected] = moveTo(from, to, workB, solder, pins(index).value);
        if connected == 1
            if (pins(index).value - length(newMoves(:,1))) > 0
                workB = workB_;
                solder = solder_;
                W = [W; newMoves];
            end
        end
        toIndex=intersect(find(current_pin.rows==to(1)),find(current_pin.cols==to(2)));
        current_pin.rows = rmrow(current_pin.rows,toIndex);
        current_pin.cols = rmrow(current_pin.cols,toIndex);
        num = num + 1;
    end
    pins(index).value = 0;
    [c,index]=min(cost(B,pins)');
end
end

function c=cost(B,pins)
for pin = 1:length(pins)
    c(pin) = (pins(pin).num*pins(pin).value/(max(pins(pin).rows)-min(pins(pin).rows))/(max(pins(pin).cols)-min(pins(pin).cols)))^-1;
    if (c(pin)==0)
        c(pin) = inf;
    end
end
end

function [from, to]=findShortestPath(solder,current_pin)
shortest = inf;
from = [];
to = [];
for pinLooper = 1:length(current_pin.rows)
    for solderLooper = 1:length(solder.rows)
        if abs(solder.rows(solderLooper)-current_pin.rows(pinLooper)) + abs(solder.cols(solderLooper)-current_pin.cols(pinLooper)) < shortest
            shortest = abs(solder.rows(solderLooper)-current_pin.rows(pinLooper)) + abs(solder.cols(solderLooper)-current_pin.cols(pinLooper));
            to = [current_pin.rows(pinLooper) current_pin.cols(pinLooper)];
            from = [solder.rows(solderLooper) solder.cols(solderLooper)];
        end
    end
end
end

function [newMoves, workB, solder, yoho] = moveTo(from, to, workB, solder, val)
newMoves = [];
yoho = 0;

fromRow = from(1);
fromCol = from(2);
toRow = to(1);
toCol = to(2);

xDir = sign(toCol - fromCol);
yDir = sign(toRow - fromRow);

% in the righ column
if xDir==0
    % the end is right next door
    if (fromRow + yDir) == toRow
        newMoves = [fromRow, fromCol, fromRow+yDir, fromCol];
        solder.rows = [solder.rows; fromRow+yDir];
        solder.cols = [solder.cols; fromCol];
        yoho = 1;
        return
    end
    % can move in the desired direction
    if fromRow+yDir > 0 && fromRow+yDir < length(workB(:,1))
        if (workB((fromRow+yDir),fromCol)==0)
            workB(fromRow+yDir,fromCol)=-val;
            [tmpMove, tmpWorkB, tmpSolder, tmpYoho] = moveTo([(fromRow+yDir),fromCol],to,workB,solder,val);
            yoho = tmpYoho;
            newMoves = [tmpMove; fromRow, fromCol, fromRow+yDir, fromCol];
            solder.rows = [tmpSolder.rows; fromRow+yDir];
            solder.cols = [tmpSolder.cols; fromCol];
            workB=tmpWorkB;
            workB(fromRow+yDir,fromCol)=-val;
            return
        end
    end
    % can move perpendicular
    if fromCol+1 > 0 && fromCol+1 < length(workB(1,:))
        if (workB(fromRow,(fromCol + 1))==0)
            workB(fromRow,fromCol+1)=-val;
            [tmpMove, tmpWorkB, tmpSolder, tmpYoho] = moveTo([fromRow,(fromCol + 1)],to,workB,solder,val);
            yoho = tmpYoho;
            newMoves = [tmpMove; fromRow, fromCol, fromRow, fromCol+1];
            solder.rows = [tmpSolder.rows; fromRow];
            solder.cols = [tmpSolder.cols; fromCol+1];
            workB=tmpWorkB;
            workB(fromRow,fromCol+1)=-val;
            return
        end
    end
    if fromCol-1 > 0 && fromCol-1 < length(workB(1,:))
        if (workB(fromRow,(fromCol - 1))==0)
            workB(fromRow,fromCol-1)=-val;
            [tmpMove, tmpWorkB, tmpSolder, tmpYoho] = moveTo([fromRow,(fromCol - 1)],to,workB,solder,val);
            yoho = tmpYoho;
            newMoves = [tmpMove; fromRow, fromCol, fromRow, fromCol-1];
            solder.rows = [tmpSolder.rows; fromRow];
            solder.cols = [tmpSolder.cols; fromCol-1];
            workB=tmpWorkB;
            workB(fromRow,fromCol-1)=-val;
            return
        end
    end
    % last option is to move away
    if fromRow-yDir > 0 && fromRow-yDir < length(workB(:,1))
        if (workB((fromRow-yDir),fromCol)==0)
            workB(fromRow-yDir,fromCol)=-val;
            [tmpMove, tmpWorkB, tmpSolder, tmpYoho] = moveTo([(fromRow-yDir),fromCol],to,workB,solder,val);
            yoho = tmpYoho;
            newMoves = [tmpMove; fromRow, fromCol, fromRow-yDir, fromCol];
            solder.rows = [tmpSolder.rows; fromRow-yDir];
            solder.cols = [tmpSolder.cols; fromCol];
            workB=tmpWorkB;
            workB(fromRow-yDir,fromCol)=-val;
            return
        end
    end
% in the right row
elseif yDir==0
    % the end is right next door
    if (fromCol + xDir) == toCol
        newMoves = [fromRow, fromCol, fromRow, fromCol+xDir];
        solder.rows = [solder.rows; fromRow];
        solder.cols = [solder.cols; fromCol+xDir];
        yoho = 1;
        return
    end
    % can move in the desired direction
    if fromCol+xDir > 0 && fromCol+xDir < length(workB(1,:))
        if (workB(fromRow,(fromCol + xDir))==0)
            workB(fromRow,fromCol+xDir)=-val;
            [tmpMove, tmpWorkB, tmpSolder, tmpYoho] = moveTo([fromRow,(fromCol + xDir)],to,workB,solder,val);
            yoho = tmpYoho;
            newMoves = [tmpMove; fromRow, fromCol, fromRow, fromCol+xDir];
            solder.rows = [tmpSolder.rows; fromRow];
            solder.cols = [tmpSolder.cols; fromCol+xDir];
            workB=tmpWorkB;
            workB(fromRow,fromCol+xDir)=-val;
            return
        end
    end
    % can move perpendicular
    if fromRow+1 > 0 && fromRow+1 < length(workB(:,1))
        if (workB(fromRow + 1,fromCol)==0)
            workB(fromRow+1,fromCol)=-val;
            [tmpMove, tmpWorkB, tmpSolder, tmpYoho] = moveTo([fromRow+1,fromCol],to,workB,solder,val);
            yoho = tmpYoho;
            newMoves = [tmpMove; fromRow, fromCol, fromRow+1, fromCol];
            solder.rows = [tmpSolder.rows; fromRow+1];
            solder.cols = [tmpSolder.cols; fromCol];
            workB=tmpWorkB;
            workB(fromRow+1,fromCol)=-val;
            return
        end
    end
    if fromRow-1 > 0 && fromRow-1 < length(workB(:,1))
        if (workB(fromRow - 1,fromCol)==0)
            workB(fromRow-1,fromCol)=-val;
            [tmpMove, tmpWorkB, tmpSolder, tmpYoho] = moveTo([fromRow-1,(fromCol)],to,workB,solder,val);
            yoho = tmpYoho;
            newMoves = [tmpMove; fromRow, fromCol, fromRow-1, fromCol];
            solder.rows = [tmpSolder.rows; fromRow-1];
            solder.cols = [tmpSolder.cols; fromCol];
            workB=tmpWorkB;
            workB(fromRow-1,fromCol)=-val;
            return
        end
    end
    % last option is to move away
    if fromCol-xDir > 0 && fromCol-xDir < length(workB(1,:))
        if (workB(fromRow,(fromCol - xDir))==0)
            workB(fromRow,fromCol-xDir)=-val;
            [tmpMove, tmpWorkB, tmpSolder, tmpYoho] = moveTo([fromRow,(fromCol - xDir)],to,workB,solder,val);
            yoho = tmpYoho;
            newMoves = [tmpMove; fromRow, fromCol, fromRow, fromCol-xDir];
            solder.rows = [tmpSolder.rows; fromRow];
            solder.cols = [tmpSolder.cols; fromCol-xDir];
            workB=tmpWorkB;
            workB(fromRow,fromCol-xDir)=-val;
            return
        end
    end
else
    [distance x_or_y] = max([abs(toCol-fromCol) abs(toRow-fromRow)]);
    if x_or_y == 1
        if fromCol+xDir > 0 && fromCol+xDir < length(workB(1,:))
            if (workB(fromRow,(fromCol + xDir))==0)
                workB(fromRow,fromCol+xDir)=-val;
                [tmpMove, tmpWorkB, tmpSolder, tmpYoho] = moveTo([fromRow,(fromCol + xDir)],to,workB,solder,val);
                yoho = tmpYoho;
                newMoves = [tmpMove; fromRow, fromCol, fromRow, fromCol+xDir];
                solder.rows = [tmpSolder.rows; fromRow];
                solder.cols = [tmpSolder.cols; fromCol+xDir];
                workB=tmpWorkB;
                workB(fromRow,fromCol+xDir)=-val;
                return
            end
        end
        if fromRow+yDir > 0 && fromRow+yDir < length(workB(:,1))
            if (workB((fromRow+yDir),fromCol)==0)
                workB(fromRow+yDir,fromCol)=-val;
                [tmpMove, tmpWorkB, tmpSolder, tmpYoho] = moveTo([(fromRow+yDir),fromCol],to,workB,solder,val);
                yoho = tmpYoho;
                newMoves = [tmpMove; fromRow, fromCol, fromRow+yDir, fromCol];
                solder.rows = [tmpSolder.rows; fromRow+yDir];
                solder.cols = [tmpSolder.cols; fromCol];
                workB=tmpWorkB;
                workB(fromRow+yDir,fromCol)=-val;
                return
            end
        end
        if fromCol-xDir > 0 && fromCol-xDir < length(workB(1,:))
            if (workB(fromRow,(fromCol - xDir))==0)
                workB(fromRow,fromCol-xDir)=-val;
                [tmpMove, tmpWorkB, tmpSolder, tmpYoho] = moveTo([fromRow,(fromCol - xDir)],to,workB,solder,val);
                yoho = tmpYoho;
                newMoves = [tmpMove; fromRow, fromCol, fromRow, fromCol-xDir];
                solder.rows = [tmpSolder.rows; fromRow];
                solder.cols = [tmpSolder.cols; fromCol-xDir];
                workB=tmpWorkB;
                workB(fromRow,fromCol-xDir)=-val;
                return
            end
        end
        if fromRow-yDir > 0 && fromRow-yDir < length(workB(:,1))
            if (workB((fromRow-yDir),fromCol)==0)
                workB(fromRow-yDir,fromCol)=-val;
                [tmpMove, tmpWorkB, tmpSolder, tmpYoho] = moveTo([(fromRow-yDir),fromCol],to,workB,solder,val);
                yoho = tmpYoho;
                newMoves = [tmpMove; fromRow, fromCol, fromRow-yDir, fromCol];
                solder.rows = [tmpSolder.rows; fromRow-yDir];
                solder.cols = [tmpSolder.cols; fromCol];
                workB=tmpWorkB;
                workB(fromRow-yDir,fromCol)=-val;
                return
            end
        end
    else
        if fromRow+yDir > 0 && fromRow+yDir < length(workB(:,1))
            if (workB((fromRow+yDir),fromCol)==0)
                workB(fromRow+yDir,fromCol)=-val;
                [tmpMove, tmpWorkB, tmpSolder, tmpYoho] = moveTo([(fromRow+yDir),fromCol],to,workB,solder,val);
                yoho = tmpYoho;
                newMoves = [tmpMove; fromRow, fromCol, fromRow+yDir, fromCol];
                solder.rows = [tmpSolder.rows; fromRow+yDir];
                solder.cols = [tmpSolder.cols; fromCol];
                workB=tmpWorkB;
                workB(fromRow+yDir,fromCol)=-val;
                return
            end
        end
        if fromCol+xDir > 0 && fromCol+xDir < length(workB(1,:))
            if (workB(fromRow,(fromCol + xDir))==0)
                workB(fromRow,fromCol+xDir)=-val;
                [tmpMove, tmpWorkB, tmpSolder, tmpYoho] = moveTo([fromRow,(fromCol + xDir)],to,workB,solder,val);
                yoho = tmpYoho;
                newMoves = [tmpMove; fromRow, fromCol, fromRow, fromCol+xDir];
                solder.rows = [tmpSolder.rows; fromRow];
                solder.cols = [tmpSolder.cols; fromCol+xDir];
                workB=tmpWorkB;
                workB(fromRow,fromCol+xDir)=-val;
                return
            end
        end
        if fromRow-yDir > 0 && fromRow-yDir < length(workB(:,1))
            if (workB((fromRow-yDir),fromCol)==0)
                workB(fromRow-yDir,fromCol)=-val;
                [tmpMove, tmpWorkB, tmpSolder, tmpYoho] = moveTo([(fromRow-yDir),fromCol],to,workB,solder,val);
                yoho = tmpYoho;
                newMoves = [tmpMove; fromRow, fromCol, fromRow-yDir, fromCol];
                solder.rows = [tmpSolder.rows; fromRow-yDir];
                solder.cols = [tmpSolder.cols; fromCol];
                workB=tmpWorkB;
                workB(fromRow-yDir,fromCol)=-val;
                return
            end
        end
        if fromCol-xDir > 0 && fromCol-xDir < length(workB(1,:))
            if (workB(fromRow,(fromCol - xDir))==0)
                workB(fromRow,fromCol-xDir)=-val;
                [tmpMove, tmpWorkB, tmpSolder, tmpYoho] = moveTo([fromRow,(fromCol - xDir)],to,workB,solder,val);
                yoho = tmpYoho;
                newMoves = [tmpMove; fromRow, fromCol, fromRow, fromCol-xDir];
                solder.rows = [tmpSolder.rows; fromRow];
                solder.cols = [tmpSolder.cols; fromCol-xDir];
                workB=tmpWorkB;
                workB(fromRow,fromCol-xDir)=-val;
                return
            end
        end
    end
end
end

function new_matrix = rmrow(old_matrix, index)
if index==1
    new_matrix = old_matrix(index+1:end,:);
elseif index==length(old_matrix(:,1))
    new_matrix = old_matrix(1:index-1,:);
else
    new_matrix = [old_matrix(1:index-1,:);old_matrix(index+1:end,:)];
end
end