Finish 2009-11-11 12:00:00 UTC

lasttry08

by Alfonso Nieto-Castanon

Status: Passed
Results: 656453 (cyc: 16, node: 3959)
CPU Time: 94.1439
Score: 6577.04
Submitted at: 2009-11-11 11:56:45 UTC
Scored at: 2009-11-11 21:29:48 UTC

Current Rank: 687th (Highest: 687th )

Comments
Please login or create a profile.
Code
function [colors,score] = solver(A,GOAL)
colors=[];

[LABELS,VALUES,IDX,R,N,S]=connected4(A);
WALL=~VALUES;
VALUES_GOAL=A(GOAL);
LABELS_GOAL=LABELS(GOAL);
[VALUES_U,VALUES_I,VALUES_J]=unique(VALUES);
VALUES_N=numel(VALUES_U);
VALUES_E=sparse(1:N,VALUES_J,true,N,VALUES_N);
UNITS=accumarray(VALUES_J,ones(N,1),[VALUES_N,1]);
COST=(VALUES_GOAL-VALUES).*S;COST(WALL)=inf;
COST1=sum(A(:));
COST2=sum(COST(~WALL));
COST3=accumarray(VALUES_J,COST);

CONNEC=connectivity;
[DISTANCES_START,DISTANCES_GOAL,DISTANCES_IDX1,DISTANCES_IDX2,DISTANCES_IDX3,VALUES_THR]=distances;
if isinf(DISTANCES_START(LABELS(GOAL))), colors=[];score=max(A(:))*sum(A>0);return;end

Z={}; COLORS=Z;C=[];
NDO=0;MAXDO=min(6,sum(DISTANCES_IDX2<=VALUES_GOAL));
COST1_TYPES=[2,3];
DO_BASELINE=1;
for N1=1:size(DISTANCES_START,2), 
    if ~isinf(DISTANCES_START(LABELS(GOAL),N1)),
        if NDO<MAXDO,
%             [Z{end+1},COLORS{end+1},C(end+1)]=evaluate(DISTANCES_START(:,N1),LABELS(GOAL));
            for COST1_TYPE=COST1_TYPES,[Z{end+1},COLORS{end+1},C(end+1)]=evaluate_stepwise_cost1(LABELS(GOAL),VALUES_THR(:,N1),DISTANCES_GOAL(:,N1));end
            NDO=NDO+1;
        end
    end; 
end
if DO_BASELINE,[COLORS{end+1},C(end+1)]=qcombo3(A,GOAL);Z{end+1}=[];end
[score,idxC]=min(C);
colors=COLORS{idxC};


function [Z,colors,C]=evaluate(d,GOAL)
    % backwards
    n=d(GOAL);
    if ~n||isinf(n),Z=[];colors=[];C=inf;return;end
    idx=zeros(1,n+1);
    idx(1)=find(d==0,1);
    idx(n+1)=GOAL;
    for n1=n+1:-1:3,
        a=find(CONNEC(:,idx(n1)));
        %b=find(d(a)==n1-2,1);
        [nill,b]=min(d(a));
        idx(n1-1)=a(b);
    end
    % forward
    Z=sparse(idx(1),1,true,N,1);
    colors=zeros(n,1);
    for n1=1:n-1,
        colors(n1)=VALUES(idx(n1+1));
        Z=Z|((CONNEC*Z>0)&VALUES_E(:,VALUES_J(idx(n1+1))));
    end
    minC=-inf;n1=0;
    % reconsider end
    while(minC<0),
        V=((CONNEC*Z)>0 & ~Z);
        COLORS_C=accumarray(VALUES_J(V),COST(V),[VALUES_N,1])+VALUES_U;
        COLORS_C(VALUES_J(idx(n+1)))=0;
        [minC,idxC]=min(COLORS_C);
        if minC<0,
            n1=n1+1;
            [nill,idxC2]=max(COLORS_C<0);
            colors(n+n1-1)=VALUES_U(idxC2);
            Z=Z|((CONNEC*Z>0)&VALUES_E(:,idxC2));
        end
    end
    % end
    colors(n+n1)=VALUES(idx(n+1));
    Z=Z|((CONNEC*Z>0)&VALUES_E(:,VALUES_J(idx(n+1))));
    if ~isempty(Z),C=COST1+(VALUES(GOAL)-VALUES(Z))'*S(Z)+sum(colors);else,C=inf;end
end

function [Z,colors,C]=evaluate_stepwise_cost1(GOAL,do,d)
    if nargin>2,units=UNITS-accumarray(VALUES_J,isinf(d),[VALUES_N,1]);else,units=UNITS;end
    % forward
    Y=sparse(1,1,true,N,1);
    W=Y;Z=Y;
    colors=zeros(N,1);
    COLORS_P=zeros(VALUES_N,3);COLORS_P(:,3)=inf;
    COLORS_C=inf+zeros(VALUES_N,1);
    COLORS_I=sparse([],[],[],N,VALUES_N);
    if nargin>2,Z0=d(1);else,Z0=DISTANCES_GOAL(1);end
    Y0=COST2-(VALUES_GOAL-VALUES(Y))*S(Y);X0=COST1-VALUES(Y)*S(Y);n3=0;
    for n1=1:N,
        % update neighborhood
        if nargin<2,V=((CONNEC*Y)>0 & ~W);
        else,V=((CONNEC*Y)>0 & ~W & do);end
        v=find(V);
        for n2=1:numel(v),
            vvalue=VALUES_J(v(n2));
            COLORS_P(vvalue,1)=VALUES(v(n2));
            COLORS_P(vvalue,2)=COLORS_P(vvalue,2)+S(v(n2));
            COLORS_P(vvalue,3)=min(COLORS_P(vvalue,3),d(v(n2)));
            COLORS_I(v(n2),vvalue)=true;
            units(vvalue)=units(vvalue)-1;
        end
        
        idx=find(COLORS_P(:,1));
        minD=min(COLORS_P(idx,3));
        k=((VALUES_GOAL-COLORS_P(idx,1)).*COLORS_P(idx,2) +COLORS_P(idx,1) );
        if COST1_TYPE==1,                   COLORS_C(idx)=COLORS_P(idx,3).*k; 
        elseif COST1_TYPE==2,               COLORS_C(idx)=(COLORS_P(idx,3)>0).*( k+(minD>0)*units(idx).*COLORS_P(idx,1) ); 
        elseif COST1_TYPE==3,               COLORS_C(idx)=units(idx);
        elseif COST1_TYPE==4,               COLORS_C(idx)=COLORS_P(idx,3);
        elseif COST1_TYPE==5,               COLORS_C(idx)=-COLORS_P(idx,3)./(1e-10+units(idx).*COLORS_P(idx,1)); 
        end
        
        [nill,idxbest]=min(COLORS_C);
        if COLORS_I(GOAL,idxbest),
            minC=-inf;n3=0;
            % reconsider end
            while(minC<0),
                V=((CONNEC*Z)>0 & ~Z);
                COLORS_C=accumarray(VALUES_J(V),COST(V),[VALUES_N,1])+VALUES_U;
                COLORS_C(VALUES_J(GOAL))=0;
                [minC,idxC]=min(COLORS_C);
                if minC<0,
                    n3=n3+1;
                    [nill,idxC2]=max(COLORS_C<0);
                    colors(n1+n3-1)=VALUES_U(idxC2);
                    Z=Z|(V&VALUES_E(:,idxC2));
                end
            end
            % end
            colors(n1+n3)=VALUES_U(VALUES_J(GOAL));
            Z=Z|((CONNEC*Z>0)&VALUES_E(:,VALUES_J(GOAL)));
            break;
        end
        
        
        
        colors(n1)=VALUES_U(idxbest);
        Y=COLORS_I(:,idxbest);
        W=W|V;
        Z=Z|Y;
        Y0=Y0-(VALUES_GOAL-COLORS_P(idxbest,1))*COLORS_P(idxbest,2);
        X0=X0-COLORS_P(idxbest,1)*COLORS_P(idxbest,2);
        COLORS_P(idxbest,:)=[0,0,inf];
        COLORS_C(idxbest)=inf;
        COLORS_I(:,idxbest)=false;
        if Z(GOAL),break;end
    end
    colors=colors(1:n1+n3,:);
    if ~isempty(Z),C=COST1+(VALUES(GOAL)-VALUES(Z))'*S(Z)+sum(colors);else,C=inf;end
    
end



function [Y1,Y2,idx1,idx2,idx3,VALUES_THR]=distances
[nill,sort3]=sort(-COST3');
%sort3=1:VALUES_N;
if min(VALUES)>0,
    VALUES_THR=repmat(cat(2,true(N,1),repmat(VALUES_J,[1,VALUES_N])~=repmat(sort3,[N,1])),[1,2]); %1:VALUES_N
    k=VALUES_N+1;
    idx1=1+sort3;%2:VALUES_N+1;
    idx2=[0;VALUES_U(sort3)];
    idx3=[0,sort3];%1:VALUES_N;
else,
    VALUES_THR=repmat(repmat(VALUES_J,[1,VALUES_N])~=repmat(sort3,[N,1]),[1,2]);%1:VALUES_N
    k=VALUES_N;
    idx1=sort3;%1:VALUES_N;
    idx2=VALUES_U(sort3);
    idx3=sort3;%1:VALUES_N;
end
X=sparse([ones(1,k),N+zeros(1,k)],1:2*k,true(1,2*k),N,2*k);
Y=inf(N,2*k);
Y(X)=0;
for n=1:N,
    X=(CONNEC*X)>0;
    X=X&(Y>n)&VALUES_THR;
    if ~any(X(:)),break;end
    Y(X)=n;
end
Y1=Y(:,1:k);Y2=Y(:,k+1:end);
end

function [G] = connectivity
[m n] = size(LABELS);
V = LABELS(:,1:n-1) ~= LABELS(:,2:n);
H = LABELS(1:m-1,:) ~= LABELS(2:m,:);
G = sparse([reshape(LABELS([V false(m,1)]),[],1); reshape(LABELS([H; false(1,n)]),[],1)], [reshape(LABELS([false(m,1) V]),[],1); reshape(LABELS([false(1,n); H]),[],1)], 1, N, N);
G = G + G' + speye(N);
G(WALL,:)=false;G(:,WALL)=false;
end

function [B,C,p,r,nc,s] = connected4(A)
% [K,a,idx,r,nc,s]=connected4(A);
% finds 4-connected components of identical elements in matrix A
%   A [m,n]
%   K [m,n] components
%   a [1,nc] values of A for each component
%   idx [1,m*n] r [1,nc+1] listed component indexes
%   such that:
%    A(idx(r(k):r(k+1)-1)=a(k)
%    K(idx(r(k):r(k+1)-1)=k
%

[m n] = size(A);
N = m*n ;
K = reshape (1:N, m, n) ;
V = A(:,1:n-1) == A(:,2:n);
H = A(1:m-1,:) == A(2:m,:);
G = sparse([reshape(K([V false(m,1)]),[],1); reshape(K([H; false(1,n)]),[],1)], [reshape(K([false(m,1) V]),[],1); reshape(K([false(1,n); H]),[],1)], 1, N, N);
G = G + G' + speye(N);
[p q r] = dmperm(G);p=p';q=q';r=r';
nc = numel(r) - 1;
C = A(p(r(1:nc)));
B = ones(m, n);
for a = 2:nc
    B(p(r(a):r(a+1)-1)) = a;
end
s=diff(r);
end

end











function [c,s] = qcombo3(A,goal)
[cc vcc ncc] = group(A);
if (max(A(:))>40)
    %[c,s] = special(A,goal,cc,vcc,ncc);
    c=[];s=inf;
else
    c = lateorearly(A,goal);
    [c,s] = glean(c,A,cc,vcc,ncc,goal);
end;
end

function [colors,score] = glean(colors,A,cc,vcc,ncc,goal)
ecc = vcc-A(goal);
hcc = hist(cc(:),1:ncc);
cben = hcc.*ecc;  % benefit of each cc
[nrow,ncol] = size(A);
flood = cc==cc(1);
for c = colors(1:end-1)'
    xflood = ~flood&([false(1,ncol);flood(1:end-1,:)]|[false(nrow,1),flood(:,1:end-1)]|[flood(2:end,:);false(1,ncol)]|[flood(:,2:end),false(nrow,1)]);
    vcc = cc(xflood&(A==c));
    flood = flood|ismember(cc,vcc);
end;
while true
    xflood = ~flood&([false(1,ncol);flood(1:end-1,:)]|[false(nrow,1),flood(:,1:end-1)]|[flood(2:end,:);false(1,ncol)]|[flood(:,2:end),false(nrow,1)]);
    cval = nonzeros(unique(A(xflood)));
    ncval = numel(cval);
    scr = zeros(1,ncval);
    vcc = cell(1,ncval);
    for i = 1:ncval
        if (cval(i)==colors(end))
            scr(i) = -inf;
        else
            vcc{i} = cc(xflood&(A==cval(i)));
            scr(i) = sum(cben(vcc{i}))-cval(i);
        end;
    end;
    [sch,ich] = max(scr);
    if (sch < 0)
        break
    end;
    colors = [colors(1:end-1);cval(ich);colors(end)];
    flood = flood|ismember(cc,vcc{ich});
end;
A(flood) = colors(end);
score = sum(A(:))+sum(colors);
end

function [colors,score] = special(A,goal,cc,vcc,ncc)
excess = A-A(goal);
ecc = vcc-A(goal);
[colors,score] = solvetaboo(A,cc,ecc,ncc,goal,[],excess);
cval = unique(A);
dear = cval < A(goal);
for i = dear
    [icolors,iscore] = solvetaboo(A,cc,ecc,ncc,goal,i,excess);
    if (iscore < score)
        score = iscore;
        colors = icolors;
    end;
end;
end


function [colors,score] = solvetaboo(A,cc,ecc,ncc,goal,taboo,excess)
[nrow,ncol] = size(A);
trow = mod(goal-1,nrow)+1;
tcol = ceil(goal/nrow);
colors = zeros(1,ncc);
flood = cc==cc(1);
move = 0;
while ~flood(goal)
    move = move+1;
    xflood = ~flood&([false(1,ncol);flood(1:end-1,:)]|[false(nrow,1),flood(:,1:end-1)]|[flood(2:end,:);false(1,ncol)]|[flood(:,2:end),false(nrow,1)]);
    cval = nonzeros(unique(A(xflood)));
    ncval = numel(cval);
    scr = rand(1,ncval);
    scr(cval > 40) = 2;
    scr(ismember(cval,taboo)) = 1.5;
    [sch,ich] = min(scr);
    colors(move) = cval(ich);
    chvcc = cc(xflood&(A==cval(ich)));
    flood = flood|ismember(cc,chvcc);
end;
colors = [colors(1:move-1) cval(cval > 40) colors(move)];
Ascr = A;
Ascr(flood) = A(goal);
score = sum(Ascr(:))+sum(colors);
end

function c = lateorearly(A, t)
B = uint8(A);
nc = max(max(A));
[G D ng] = group(B);
C = comp_cost(B, G, t, ng);
T = connections(G, D, ng);
C = push_channels(T, C);
c = dijkstra(T, nc, C, 1, G(t));
end

% Based on Tim Davis' find_components
function [B C nc] = group(A)
[m n] = size(A);
N = m*n;
K = reshape(1:N, m, n);
V = A(:,1:n-1) == A(:,2:n);
H = A(1:m-1,:) == A(2:m,:);
G = sparse([reshape(K([V false(m,1)]),[],1); reshape(K([H; false(1,n)]),[],1)], [reshape(K([false(m,1) V]),[],1); reshape(K([false(1,n); H]),[],1)], 1, N, N);
G = G + G' + speye(N);
[p q r] = dmperm(G);
nc = numel(r) - 1;
C = A(p(r(1:nc)));
B = ones(m, n, 'uint16');
for a = 2:nc
    B(p(r(a):r(a+1)-1)) = uint16(a);
end
end

% Similar idea to Dijkstra's shortest path (but not optimal here)
function [path loss Tcurr] = dijkstra(T, nC, cost, from, to)
nG = size(T, 1);
nT = ceil(nG * 1.5);
parent = ones(nG, nT, class(T));
k = zeros(nT, 1, 'uint16');
pointers = nT + ones(nG, 1, 'uint16');
pointers(from) = 1;
loss = zeros(nT+1, 1);
loss(:) = 1e9;
loss(1) = cost(from);
Tcurr = ones(nG, nT, class(T));
Tcurr(:,1) = T(:,from);
Tcurr(from,1) = 2;
sz = [nC+3 1];
noff = [0 0 0 1:nC]' * 2;
changed = false(nT, 1);
changed(1) = true;
b = 0;
while 1
    b = b + 1;
    if b > nT
        if ~any(changed)
            break;
        end
        b = 1;
    end
    if ~changed(b)
        continue;
    end
    changed(b) = false;
    if Tcurr(to,b) == 2
        continue;
    end
    ncost = accumarray(Tcurr(:,b), cost, sz);
    ncost(1:2) = 1e5;
    ncost = loss(b) + (ncost + noff) + 1;
    I = ncost(Tcurr(:,b)) < loss(pointers);
    if ~any(I)
        continue;
    end
    L = find(I)';
    [cl I] = sort(Tcurr(L,b));
    L = L(I);
    D = [0; find(diff(cl) ~= 0); numel(cl)];
    cl = cl(D(2:end));
    pointers(L) = numel(loss);
    I = true(nT+1, 1);
    I(pointers) = false;
    n = numel(cl);
    C = find(I(b+1:end-1), n) + b;
    n = n - numel(C);
    if n
        C = [C; find(I(1:b), n)];
    end
    ncost = ncost(cl);
    loss(C) = ncost;
    changed(C) = true;
    n = k(b) + 1;
    k(C) = n;
    K = Tcurr(:,b) == 1;
    for d = 1:numel(C)
        c = C(d);
        Tcurr(:,c) = Tcurr(:,b);
        J = Tcurr(:,c) == cl(d);
        Tcurr(J,c) = 2;
        Tcurr(K,c) = max(T(K,J), [], 2);
        parent(1:n,c) = parent(1:n,b);
        parent(n,c) = cl(d);
        pointers(L(D(d)+1:D(d+1))) = c;
    end
end
to_ = pointers(to);
path = parent(1:k(to_),to_) - 3;
%loss = loss(to_);
end

function G = connections(A, B, ng)
C = uint32(A);
[h w] = size(A);
T = false(ng);
I = A(1:h-1,:) ~= A(2:h,:);
X = C([I; false(1,w)]);
Y = C([false(1,w); I]);
T(X+(Y-1)*ng) = true;
T(Y+(X-1)*ng) = true;
I = A(:,1:w-1) ~= A(:,2:w);
X = C([I false(h,1)]);
Y = C([false(h,1) I]);
T(X+(Y-1)*ng) = true;
T(Y+(X-1)*ng) = true;
[y x] = find(T);
B = B + 3;
B(B==3) = 1;
G = ones(ng, class(B));
G(T) = B(y);
end

function C = comp_cost(A, B, t, ng)
C = int32(A);
C = C(t) - C(:);
C(A==0) = 1e6;
C = int32(accumarray(B(:), C, [ng 1]));
end

% Heuristic to deal with large regions connected by thin channels
function C = push_channels(T, C)
M = T > 3;
Q = find(sum(M, 1) == 1);
while ~isempty(Q)
    q = Q(1);
    r = find(M(:,q));
    if isscalar(r)
        C(r) = C(r) + C(q);
        C(q) = 0;
        M(q,r) = false;
        Q(1) = r;
    else
        Q = Q(2:end);
    end
end
end