ID:45749
Title:A02.2
Author:Andreas
Date:2008-05-01 06:33:46
Score:30674.8215
Result:306658.00 (cyc: 16, node: 870)
CPU Time:1.0952
Status:Passed
Comments:
Based on:none
Code:
function wires = solver(B)

    Bsize = size(B);
    % wires = zeros(ceil((Bsize(1)+Bsize(2))/2), 4);
    wires = zeros( ((Bsize(1)-1) * Bsize(2)) + (Bsize(1) * (Bsize(2)-1)), 4);
    nwires = 0;
    
    pValues = unique(B(B>0))';
    
    nPins = size(pValues, 2);
    pCounts = zeros(size(pValues));

    for j = 1:nPins
        pCounts(j) = nnz(B == pValues(j));
    end

    
    %% skip single pins
    
    skip = pCounts == 1;
    if any(skip)
        nPins = nPins - sum(skip);
        %         skippins = pValues(skip);
        %         nskippins = sum(skip);
        %         for j = 1:nskippins
        %             B(B==skippins(j)) = -1;
        %         end
        pValues = pValues(~skip);
        pCounts = pCounts(~skip);
    end
      
    
    %% create distance and connection matrices and add simple wires
    pDistances    = cell(1, nPins);
    pTriDistances = cell(1, nPins);
    pDistancesX   = pDistances;
    pDistancesY   = pDistances;
    pConnected    = pDistances;
    pXvs          = pDistances;
    pYvs          = pDistances;
    
    for pix = 1:nPins
        [pXvs{pix} pYvs{pix}] = find(B == pValues(pix));
        pConnected{pix}    = false(pCounts(pix));
        pDistancesX{pix}   = bsxfun(@(x1, x2) abs(x1-x2), pXvs{pix}, pXvs{pix}');
        pDistancesY{pix}   = bsxfun(@(y1, y2) abs(y1-y2), pYvs{pix}, pYvs{pix}');
        pDistances{pix}    = pDistancesX{pix} + pDistancesY{pix};
        pTriDistances{pix} = triu(pDistances{pix});
        
        % add wires for adjacent pins immediately
        adjacent = pTriDistances{pix} == 1;
        if any(any(adjacent))
            [aix1 aix2] = find(adjacent);
            nadjacent = length(aix1);
            for j = 1:nadjacent
                pConnected{pix}(aix1(j), aix2(j)) = true;
                pConnected{pix}(aix2(j), aix1(j)) = true;
                % disp(['adjacent: <' num2str([pXvs{pix}(aix1(aix)) pYvs{pix}(aix1(aix)) pXvs{pix}(aix2(aix)) pYvs{pix}(aix2(aix))]) '> ?']);
            end
            [wires nwires] = addwires(wires, nwires, [pXvs{pix}(aix1) pYvs{pix}(aix1) pXvs{pix}(aix2) pYvs{pix}(aix2)]);
        end
    end 
        
    %% check for wires of length 2
    [sv svix] = sort(pValues, 'descend');
    
    for cix = 1:nPins
        pix = svix(cix);

        d2b = pTriDistances{pix} == 2;
        
        if any(any(d2b))
            d2bstraight = d2b & pDistancesX{pix} ~= 1;
            d2bcorner   = d2b & ~d2bstraight;
            
            if any(any(d2bstraight))
                [ix1 ix2] = find(d2bstraight);
                pins = [pXvs{pix}(ix1) pYvs{pix}(ix1) pXvs{pix}(ix2) pYvs{pix}(ix2)];
                midpoints     = (pins(:, [1, 2]) + pins(:, [3, 4])) / 2;
                midpointsfree = pointsfree(B, midpoints);
                %                 midpointsfree = false(size(midpoints, 1), 1);
                %                 for j = 1:size(midpoints, 1);
                %                     if ~B(midpoints(j, 1), midpoints(j, 2))
                %                         midpointsfree(j) = true;
                %                         pConnected{pix}(ix1(j), ix2(j)) = true;
                %                         pConnected{pix}(ix2(j), ix1(j)) = true;
                %                     end
                %                 end
                if any(midpointsfree)
                    pins      = pins(midpointsfree, :);
                    midpoints = midpoints(midpointsfree, :);
                    for j = 1:size(midpoints, 1)
                        pConnected{pix}(ix1(j), ix2(j)) = true;
                        pConnected{pix}(ix2(j), ix1(j)) = true;
                    end
                    [wires nwires] = addwires(wires, nwires, [ ...
                        pins(:, [1, 2]) midpoints; ...
                        pins(:, [3, 4]) midpoints]);
                end
            end
            
            if any(any(d2bcorner))
                [ix1 ix2] = find(d2bcorner);
                pins = [pXvs{pix}(ix1) pYvs{pix}(ix1) pXvs{pix}(ix2) pYvs{pix}(ix2)];
                n = size(ix1, 1);
                midpoints = [pins(:, 1) pins(:, 4); pins(:, 3) pins(:, 2)];
                midpointsfree = pointsfree(B, midpoints);
                for j = 1:n
                    pick = false;
                    if midpointsfree(j)
                        freemidpoint = midpoints(j, :);
                        pick = true;
                    elseif midpointsfree(j+n)
                        freemidpoint = midpoints(j+n, :);
                        pick = true;
                    end
                    if pick
                        [wires nwires] = addwires(wires, nwires, [ ...
                            pins(j, [1, 2]) freemidpoint; ...
                            pins(j, [3, 4]) freemidpoint]);
                    end
                end
            end
                
            
        end
    end
    
    %             pConnected{pix} = convexconnections(pConnected{pix});
    
    
    %% find high-values
    
%     % pPotential = pValues .* pCounts;
%     pPotential = pValues;
% 
%     [mp mpix] = sort(pPotential, 'descend');
% 
%     for cix = 1:nPins
%         pix = mpix(cix);
%         
%         connected  = pConnected{pix};
%         distances  = pDistances{pix};
%         distancesX = pDistancesX{pix};
%         distancesY = pDistancesY{pix};
%         xvs        = pXvs{pix};
%         yvs      = pYvs{pix};
%         
%         
%         
%     
%     end
    
   wires = wires(1:nwires, :);
   % wires = zeros(0, 4);
end
    

function ret = pointsfree(B, points)
    ret = false(size(points, 1), 1);
    for j = 1:size(points, 1);
        if ~B(points(j, 1), points(j, 2))
            ret(j) = true;
        end
    end
end

    
function [wires nwires] = addwires(wires, nwires, newwires)
    nnewwires = size(newwires, 1);
    wires(nwires+1:nwires+nnewwires, :) = newwires;
    nwires = nwires + nnewwires;
end


function connected = convexconnections(connected)
    if ~any(any(connected)) return; end
    nc = nnz(connected);
    while true
        connected = connected + connected ^ 2;
        newnc = nnz(connected);
        if nc ~= newnc nc = newnc;
        else           break;
        end
    end    
    connected = ~(~connected | eye(size(connected)));
end
    
function d = d(x1, y1, x2, y2)
    d=sum(abs([x1-y1,x2-y2]));
end