ID:45867
Title:Elbow Grease Connection #2
Author:DreadNox
Date:2008-05-01 12:12:18
Score:20909.7865
Result:208918.00 (cyc: 16, node: 770)
CPU Time:25.8635
Status:Passed
Comments:
Based on:none
Code:
%% Main Solver Function
function W = solver3(B)

BB = B; % board's copy
%BB = repmat(B, [1 1 2]); % represent wires and pins together, a bridge
%means a switch in the 3rd dimension from one board to the other
pinNbr = sort(unique(B(B>0)), 'descend');
szB = size(B);
%neighbIdx = [ -1 br 1 -br ]; % [ ^ > v < ]
W = zeros(0,4);
for n = pinNbr.'
    
    pinSet = find(B == n);
    if numel(pinSet) == 1, continue, end; % for connecting purposes ignore pins with only one occurrence

    p = 1;
    pinSetOut = [ pinSet zeros(numel(pinSet),1) ]; % 2nd column: 1 means unable to connected since last wire was added
    w = [];
    while ~all(pinSetOut(:,2)) && isempty(w) && p < size(pinSetOut,1)
        p1 = pinSetOut(p,1);
        [ign, d] = sort(setDist(szB, p1, pinSet), 'ascend'); % first distance will be zero (same point)
        pinSetOut(p,2) = 1; % assume connection attempt is going to fail
        for k = 2:numel(d)
            p2 = pinSet(d(k));
            [w, widx] = elbowConn(BB, p1, p2);
            if ~isempty(w)
                W = [ W; w ];
                BB(widx) = BB(p1); % "paint' wire on board
                pinSet = [ p1; p2; widx(:) ]; % add new "pins', connection points
                pinSetOut([p d(k)],:) = []; % remove endpoints pins from unconnected
                break;
            end
        end
        if ~isempty(pinSetOut) && isempty(w) % if indeed attempt failed, move on to the next
            p = p + 1;
        end
    end

    if isempty(w), continue, end; % unable to make connection between the initial group of pins
    
    % connected remaining pins to the previously created connected
    % component
    p = 1; % restart from top
    pinSetOut(:,2) = 0; % reset connection attempt
    while ~all(pinSetOut(:,2))
        p1 = pinSetOut(p,1);
        [ign, d] = sort(setDist(szB, p1, pinSet), 'ascend'); % first distance will be zero (same point)
        pinSetOut(p,2) = 1; % assume connection attempt is going to fail
        for k = 1:numel(d)
            p2 = pinSet(d(k));
            [w, widx] = elbowConn(BB, p1, p2);
            if ~isempty(w)
                W = [ W; w ];
                BB(widx) = BB(p1); % "paint' wire on board
                pinSet = [ pinSet; p1; widx(:) ]; % add outside pin and new wire-"pins', connection points
                pinSetOut(p,:) = []; % remove outside pin from unconnected
                p = 1; % restart from top
                pinSetOut(:,2) = 0; % reset connection attempt
                %visualize(B,w,1);
                %pause(0.3)
                break;
            end
        end
        if ~isempty(pinSetOut) && pinSetOut(p,2) % if indeed attempt failed, move on to the next
            p = p + 1;
        end
    end
end

end % solver3

%% Elbow Connection
%  Attempts to create an *elbow* connection between p1 and p2. Sees other
%  not compatible wires are obstacle - *does not use bridges*.
function [W, Widx] = elbowConn(B, p1, p2)

[br, bc] = size(B);
n = B(p1);
W = zeros(0,4);
Widx = [];

[i1, j1] = ind2sub([br bc], p1);
[i2, j2] = ind2sub([br bc], p2);

istep = sign(i2-i1);
jstep = sign(j2-j1);
if istep == 0 % <=> i1 == i2
    vhline = i2 + ((j1+jstep:jstep:j2-jstep)-1)*br; % horizontal traverse
    if all( ~B(vhline) | B(vhline) == n )
        W = idx2wire([br bc], [p1 vhline p2]);
        Widx = vhline;
    end
elseif jstep == 0 % <=> j1 == j2
    hvline = (i1+istep:istep:i2-istep) + (j2-1)*br; % vertical traverse
    if all( ~B(hvline) | B(hvline) == n )
        W = idx2wire([br bc], [p1 hvline p2]);
        Widx = hvline;
    end
else
    vhline = [ (i1+istep:istep:i2) + (j1-1)*br ... % vertical traverse
        i2 + ((j1+jstep:jstep:j2-jstep)-1)*br ]; % horizontal traverse
    if all( ~B(vhline) | B(vhline) == n )
        W = idx2wire([br bc], [p1 vhline p2]);
        Widx = vhline;
    else
        hvline = [ i1 + ((j1+jstep:jstep:j2)-1)*br ... % horizontal traverse
            (i1+istep:istep:i2-istep) + (j2-1)*br ]; % vertical traverse
        if all( ~B(hvline) | B(hvline) == n )
            W = idx2wire([br bc], [p1 hvline p2]);
            Widx = hvline;
        end
    end
end

end % elbowConn

%% Index list to wire list
function W = idx2wire(szB, idxList)

[Wi Wj] = ind2sub(szB, idxList.');
W = [ Wi(1:end-1) Wj(1:end-1) Wi(2:end) Wj(2:end) ];

end % idx2wire

%% Manhattan distance between an index and a set of indexes
function d = setDist(sz,k,kset)

[i j] = ind2sub(sz,[k; kset(:)]);
d = abs(i(1)-i(2:end)) + abs(j(1)-j(2:end));

end % dist