Winner the cyclist (CT 1)

Finish 2005-11-09 09:00:00 UTC

AMix3

by Abhisek Ukil

Status: Passed
Results: 1483.4788
CPU Time: 77.2504
Score: 170.991
Submitted at: 2005-11-06 07:23:22 UTC
Scored at: 2005-11-06 07:36:42 UTC

Current Rank: 1384th

Comments
Please login or create a profile.
Code
%Based on Hoffa

function solution = solver(puzzle,list)
% SOLUTION = SOLVER(PUZZLE,LIST) Sudoku solver
NUMREPS=10000;
NUMRUNS=11;
h = reshape(1:9,3,3);
g = ceil((1:9)/3);
h = (h(g,g)-1)*9 + repmat(h,3);
blocks = ceil(h/9);
h1=reshape(1:81,9,9);
iX=[h h1 h1'];
rand('seed',1);

q = find(~puzzle);
missing = numel(q);
listO=list;
solution = puzzle;
% Calculate the average of all values available
total_puzzle = sum(sum(puzzle));
total_all = sum(list) + total_puzzle;
total_count = (81 - missing) + numel(list);
average = total_all / total_count;
target = average*9;
bestscore2 = 1e10;
bestscore=1e10;
block_errors = zeros(1,9);

for run= 1:NUMRUNS
    % Fill in values to optimize the rows
    list=listO;
    list_left = numel(list);
    solution=puzzle;
    %    Fill in values to optimize the rows
    for r = 1:9
        %    Fill in values for all empty spaces in this row
        for c = 1:9
            if puzzle(r,c) == 0
                list_index = ceil(rand*list_left);
                list_value = list(list_index);
                list(list_index:list_left-1) = list(list_index+1:list_left);
                list(list_left) = 1e10;
                list_left = list_left-1;
                solution(r,c) = list_value;
            end;
        end;
        if list_left
            %       Get row as close as possible to target value
            row_total = sum(solution(r,:)) - target;
            est_error = abs(row_total);
            tq=find(puzzle(r,:)==0);
            colv=tq(ceil(rand(300,1)*length(tq)));
            for tries = 1:300
                col = colv(tries);
                list_index = ceil(rand*list_left);
                list_value = list(list_index);
                delta=list_value - solution(r,col);
                new_est_error = abs(row_total + delta);
                if (new_est_error < est_error)
                    row_total=row_total + delta;
                    est_error = new_est_error;
                    list(list_index) = solution(r,col);
                    solution(r,col) = list_value;
                end;
            end;
        end;
    end;
    target = sum(sum(solution))/9;
    col_selection = [[4 5 6 7 8 9];[7 8 9 7 8 9]];
    %Go about optimizing blocks without changing rows
    for rb = 1:3
        scale_row = (rb-1)*3;
        for cb = 1:2
            scale_col = (cb-1)*3;
            cols_all_outside = col_selection(cb,:);
            block = sum(sum(solution(scale_row+1:rb*3,scale_col+1:cb*3)));
            for tries = 1:200
                row = scale_row + ceil(rand*3);
                col_inside = scale_col + ceil(rand*3);
                if (puzzle(row,col_inside) == 0)
                    val_inside = solution(row,col_inside);
                    col_index = ceil(rand*6);
                    col_outside = cols_all_outside(col_index);
                    if (puzzle(row,col_outside) == 0)
                        val_outside = solution(row,col_outside);
                        error = abs(block - target);
                        error_new = abs(block + val_outside - val_inside - target);
                        if (error_new < error)
                            solution(row,col_outside) = val_inside;
                            solution(row,col_inside) = val_outside;
                            block = block - val_inside + val_outside;
                        end;
                    end;
                end;
            end;
        end;
    end;
    index = 1;
    for rb = 1:3
        scale_row = (rb-1)*3;
        for cb = 1:3
            scale_col = (cb-1)*3;
            block = sum(sum(solution(scale_row+1:rb*3,scale_col+1:cb*3)));
            block_errors(index) = block - target;
            index = index + 1;
        end;
    end;
    %Solve the columns without changing rows or blocks
    col_total = sum(solution)-target;
    for tries = 1:1000
        col = ceil(rand*9);
        error = abs(col_total(col));
        row = ceil(rand*9);
        value = solution(row,col);
        if (puzzle(row,col) == 0)
            col_swap = ceil(rand*3) + (ceil(col/3)-1)*3;
            value_swap = solution(row,col_swap);
            if (puzzle(row,col_swap) == 0)
                col_swap_total = col_total(col_swap);
                error_swap = abs(col_swap_total);
                error_total = error + error_swap;
                col_total_new = col_total(col) + value_swap - value;
                error_new = abs(col_total_new);
                col_swap_total_new = col_swap_total + value - value_swap;
                error_swap_new = abs(col_swap_total_new);
                error_total_new = error_new + error_swap_new;
                if (error_total_new < error_total)
                    solution(row,col) = value_swap;
                    solution(row,col_swap) = value;
                    col_total(col_swap)=col_swap_total_new;
                    col_total(col)=col_total_new;
                end;
            end;
        end;
    end;
    sums  = sum(solution(iX));
    score = sum(abs(sum(sums)/27-sums));
    if (score<bestscore)
        bestinit=solution;
        bestscore=score;
        bestlist=list;
    end
    lq=length(q);
    index1v = ceil(rand(NUMREPS,1)*lq);
    index2v = mod((index1v+floor(rand(NUMREPS,1)*(lq-1))),lq)+1;
    index1v = q(index1v);
    index2v = q(index2v);
    solution=bestinit;
    list=bestlist;
    target = sum(sum(solution))/9;
    rowtotals=sum(solution,2);
    coltotals=sum(solution);
    blocktotals=sum(solution(h));
    for rep= 1:NUMREPS
        index1 = index1v(rep);
        index2 = index2v(rep);
        index1r = mod(index1-1,9)+1;
        index2r = mod(index2-1,9)+1;
        index1c = ceil(index1/9);
        index2c = ceil(index2/9);
        if (rand > 0.8) & (list_left ~= 0)
            value1 = solution(index1r,index1c);
            block1i = blocks(index1r,index1c);
            subtotal1_old = rowtotals(index1r) + coltotals(index1c) + blocktotals(block1i);
            score1_old = abs(subtotal1_old-3*target);
            list_index = ceil(rand*list_left);
            replace = list(list_index);
            score1_new = abs(subtotal1_old+3*replace-3*value1-3*target);
            if (score1_new - score1_old) < rand
                solution(index1r,index1c) = replace;
                list(list_index) = value1;
                rowtotals(index1r)=rowtotals(index1r)+replace-value1;
                coltotals(index1c)=coltotals(index1c)+replace-value1;
                blocktotals(block1i)=blocktotals(block1i)+replace-value1;
                target = sum(sum(solution))/9;
            end;
        else
            value1 = solution(index1r,index1c);
            value2 = solution(index2r,index2c);
            block1i = blocks(index1r,index1c);
            block2i = blocks(index2r,index2c);
            subtotal1_old = rowtotals(index1r) + coltotals(index1c) + blocktotals(block1i);
            subtotal2_old = rowtotals(index2r) + coltotals(index2c) + blocktotals(block2i);
            subscore1_old = abs(subtotal1_old-3*target);
            subscore2_old = abs(subtotal2_old-3*target);
            subscoret_old = subscore1_old + subscore2_old;
            delta1 = 3*value1;
            delta2 = 3*value2;
            subtotal1_new = subtotal1_old - delta1 + delta2;
            subtotal2_new = subtotal2_old - delta2 + delta1;
            subscore1_new = abs(subtotal1_new-3*target);
            subscore2_new = abs(subtotal2_new-3*target);
            subscoret_new = subscore1_new + subscore2_new;
            if (subscoret_new - subscoret_old) < (rand/6)
                solution(index1r,index1c) = value2;
                solution(index2r,index2c) = value1;
                if (index1r~=index2r)
                    rowtotals(index1r)=rowtotals(index1r)+value2-value1;
                    rowtotals(index2r)=rowtotals(index2r)+value1-value2;
                end
                if (index1c~=index2c)
                    coltotals(index1c)=coltotals(index1c)+value2-value1;
                    coltotals(index2c)=coltotals(index2c)+value1-value2;
                end
                if (block1i~=block2i)
                    blocktotals(block1i)=blocktotals(block1i)+value2-value1;
                    blocktotals(block2i)=blocktotals(block2i)+value1-value2;
                end
            end;
        end;
    end;
    sums  = sum(solution(iX));
    score = sum(abs(sum(sums)/27-sums));
    if (score<bestscore2)
        bestsol=solution;
        bestscore2=score;
        bestlist2=list;
        if score<5
            return
        end
    end
end;
%solution=bestsol;

%-----Further Improvement--------------
S_best=bestsol;
Result_best=checkresult(S_best);

solution1=rearrange(puzzle,S_best,1);
solution2=rearrange(puzzle,S_best,2);
Result1=checkresult(solution1);
Result2=checkresult(solution2);

[decideVal,decideIndex]=min([Result_best Result1 Result2]);

switch decideIndex
    case 1
        solution=S_best;
    case 2
        solution=solution1;
    case 3
        solution=solution2;
end
%---------------------------------------------


X=solution(iX);
list=bestlist2(bestlist2<1e6);
sX=sum(X);
mX=sum(sX)/27;
q=q';
[solution,X,sX,mX,list]=improver1(solution,X,sX,mX,list,iX,q,100);
[solution,X,sX,bv]=improver2(solution,X,sX,mX,iX,q,18);
if ~bv;return;end;
[solution,X,sX,mX,list,bv]=improver1(solution,X,sX,mX,list,iX,q,100);
if ~bv;return;end;
[solution,X,sX,bv]=improver2(solution,X,sX,mX,iX,q,20);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [puzzle,X,sX,mX,list,bv]=improver1(puzzle,X,sX,mX,list,iX,iList,n);
bv=0;
if numel(list)
    for iRepeat=1:n
        bVerb=0;
        for i=iList
            bV=0;
            x=puzzle(i);
            bbb=iX==i;
            iii=sum(bbb)>0;
            Xhoog=sX>mX;
            nXh=sum(Xhoog);
            nXhi=sum(Xhoog(iii));
            dx=list-x;
            dS=(nXhi-nXh/9)*dx;
            j=find(dS<0);
            if numel(j)
                dx=dx(j);
                Nh=dx;
                Nhi=dx;
                for k=1:length(j)
                    Nh(k)=sum(sX>mX+dx(k)/9);
                    Nhi(k)=sum(sX(iii)>mX-8/9*dx(k));
                end
                bNOK=(Nhi-Nh/9)*(nXhi-nXh/9)<0;
                j(bNOK)=[];
                if length(j)
                    dx(bNOK)=[];
                    if 1
                        if dx(1)>0
                            k=length(j);
                        else
                            k=1;
                        end
                    else
                        [mx,k]=max(abs(dx));
                    end
                    dx=dx(k);
                    j=j(k);
                    bV=1;
                end
            end
            if bV
                X(bbb)=list(j);
                sX=sum(X);
                mX1=mX+dx/9;
                puzzle(i)=list(j);
                bVerb=1;
                list(j)=x;
                mX=mX1;
                bv=1;
            end
        end
        if ~bVerb;break;end
    end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [puzzle,X,sX,bv]=improver2(puzzle,X,sX,mX,iX,iList,n);
bv=1;
sX0=sum(abs(sX-mX));
for i=1:n
    bVerb=0;
    for iEl=iList
        x=puzzle(iEl);
        I=find(sum(iX==iEl));
        s=sum(sX(I)-mX);
        dx=puzzle(iList)-x;
        S0=sX-mX;
        if s>0
            j=find(dx<0&dx+s*2>0);
        else
            j=find(dx>0&dx+s*2<0);
        end
        if numel(j)
            T0=sum(abs(S0));
            m=0;
            for k=1:length(j)
                S=S0;
                S(I)=S(I)+dx(j(k));
                J=find(sum(iX==iList(j(k))));
                S(J)=S(J)-dx(j(k));
                T=sum(abs(S));
                if T<T0
                    m=k;
                    T0=T;
                end
            end
            if m
                j=iList(j(m));
                puzzle(iEl)=puzzle(j);
                puzzle(j)=x;
                X=puzzle(iX);
                sX=sum(X);
                bVerb=1;
                bv=1;
            end
        end
    end
    if ~bVerb;break;end
end 

%--------------------------------------------------------
% Rearrange
function result=rearrange(a,ar,flag)
result=[];
R=checkresult(ar);
aar=ar;
if flag==1 %row wise
    for i=1:9
        pres=R;
        [val,index]=setdiff(aar(i,:),a(i,:));
        n=numel(val);
        shift=ones(1,n);
        % Only Circular shift
        for j=1:n-1
            val=circshift(val,shift);
            aar(i,index)=val;
            res=checkresult(aar);
            if res<0.5*R
                result=aar;
                break
            elseif res<R && res>=0.5*R && res<=pres
                result=aar;
                pres=res;
            elseif res>R
                aar=ar;
            end
        end
        
        %if res>R, aar=ar; end
        
        %Other shifts, swap 1st-last and shift
        if n>2
            [nval,index]=setdiff(aar(i,:),a(i,:));
            temp=nval(1); nval(1)=nval(end); nval(end)=temp; %swap 1st and last
            % Circular shift
            for j=1:n-1
                nval=circshift(nval,shift);
                aar(i,index)=nval;
                res=checkresult(aar);
                if res<0.2*R
                    result=aar;
                    return
                    %break
                elseif res<R && res>=0.2*R && res<=pres
                    result=aar;
                    pres=res;
                elseif res>R
                    aar=ar;
                end
            end
        end
        
        %if res>R, aar=ar; end
        
        
    end
else %columnwise
    for i=1:9
        pres=R;
        [val,index]=setdiff(aar(:,i),a(:,i));
        n=numel(val);
        shift=ones(1,n);
        % Only Circular shift
        for j=1:n-1
            val=circshift(val,shift);
            aar(index,i)=val;
            res=checkresult(aar);
            if res<0.5*R
                result=aar;
                break
            elseif res<R && res>=0.5*R && res<=pres
                result=aar;
                pres=res;
            elseif res>R
                aar=ar;
            end
        end
        
        %if res>R, aar=ar; end
        
        %Other shifts, swap 1st-last and shift
        if n>2
            [nval,index]=setdiff(aar(:,i),a(:,i));
            temp=nval(1); nval(1)=nval(end); nval(end)=temp; %swap 1st and last
            % Circular shift
            for j=1:n-1
                nval=circshift(nval,shift);
                aar(index,i)=nval;
                res=checkresult(aar);
                if res<0.2*R
                    result=aar;
                    return
                elseif res<R && res>=0.2*R && res<=pres
                    result=aar;
                    pres=res;
                elseif res>R
                    aar=ar;
                end
                
            end
        end
        
        %if res>R, aar=ar; end
    end
end

if result
    result=result;
    return;
else
    c=setdiff(aar,ar,'rows');
    if c
        result=aar;
    else
        result=ar;
    end
end
%--------------------------------------------------------
% Check Result
function result=checkresult(a)

%blocks
block=[1 2 3 10 11 12 19 20 21
    4 5 6 13 14 15 22 23 24
    7 8 9 16 17 18 25 26 27
    28 29 30 37 38 39 46 47 48
    31 32 33 40 41 42 49 50 51
    34 35 36 43 44 45 52 53 54
    55 56 57 64 65 66 73 74 75
    58 59 60 67 68 69 76 77 78
    61 62 63 70 71 72 79 80 81];

target=sum(a(:))/9;
regSum=sum(a(block'));
colSum=sum(a);
rowSum=sum(a');
result=sum(abs(colSum-target))+sum(abs(rowSum-target))+sum(abs(regSum-target));