Winner the cyclist (CT 1)

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

the mystery entry

by Niilo Sirola

Status: Failed
Results:

Based on: SHsudo16 (diff)
Basis for: gt16 (diff)

Comments
Niilo Sirola
09 Nov 2005
minor re-ordering
Please login or create a profile.
Code
function solution = solver(puzzle,list)

rand('seed',1);

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

col_selection = [[4 5 6 7 8 9];[7 8 9 7 8 9]];
blockmap=[1     1     1     4     4     4     7     7     7
     1     1     1     4     4     4     7     7     7
     1     1     1     4     4     4     7     7     7
     2     2     2     5     5     5     8     8     8
     2     2     2     5     5     5     8     8     8
     2     2     2     5     5     5     8     8     8
     3     3     3     6     6     6     9     9     9
     3     3     3     6     6     6     9     9     9
     3     3     3     6     6     6     9     9     9];
rowmap = [1     1     1     1     1     1     1     1     1
     2     2     2     2     2     2     2     2     2
     3     3     3     3     3     3     3     3     3
     4     4     4     4     4     4     4     4     4
     5     5     5     5     5     5     5     5     5
     6     6     6     6     6     6     6     6     6
     7     7     7     7     7     7     7     7     7
     8     8     8     8     8     8     8     8     8
     9     9     9     9     9     9     9     9     9];
colmap = [1     2     3     4     5     6     7     8     9
     1     2     3     4     5     6     7     8     9
     1     2     3     4     5     6     7     8     9
     1     2     3     4     5     6     7     8     9
     1     2     3     4     5     6     7     8     9
     1     2     3     4     5     6     7     8     9
     1     2     3     4     5     6     7     8     9
     1     2     3     4     5     6     7     8     9
     1     2     3     4     5     6     7     8     9];


[solution,s]    =solverC(puzzle,list);                                                            
if floor(s) == 19
	[sol2,s2]       =solverC(puzzle(:,end:-1:1),list);
	if s2<s
		solution=sol2(:,end:-1:1);
		s=s2;
	end
end 
if s > 200
	[sol2,s2]       =solverC(puzzle(end:-1:1,:),list);
	if s2<s
		solution=sol2(end:-1:1,:);
		s=s2;
	end
end

idx=find(puzzle==0);
[solution1,s2]  =improver3(list,solution,idx);
if s2<s
	solution=solution1;
	s=s2;
end     
if s>100
	[solution1,s2]  =improver3(list,solution,idx);
	if s2<s
		solution=solution1;
	end
end

flag=1;
while flag
  [solution,flag]=improver4(solution,list,idx);
end;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [solution,s] = solverC(puzzle,list)
NUMREPS = 25000;
NUMTRIES1 = 200;
NUMTRIES2 = 200;
NUMTRIES3 = 300;

global h iX iN col_selection blockmap rowmap colmap;

free = puzzle==0;
q = uint8(find(free)');
missing = numel(q);
lq = missing;
list_count = numel(list);
listO=list;
NUMRUNS = (list_count / 10)+10;
% Calculate the average of all values available
total_puzzle = sum(sum(puzzle));
total_all = sum(list) + total_puzzle;
total_count = (81 - missing) + list_count;
average = total_all / total_count;
target = average*9;
bestscore2 = 1e10;
bestscore = 1e10;
reruns=0;

index1v = ceil(rand(1,NUMREPS)*lq);
index1v = q(index1v);
index2v = mod((index1v+uint8(floor(rand(1,NUMREPS)*(lq-1)))),lq)+1;
index2v = q(index2v);

id=1:9;

if target>600
    idT=sum(free);
    [tempT,id]=sort(idT,'descent');
end

while reruns<3
	for run = 1:NUMRUNS
		% Fill in values to optimize the rows
		list = listO;
		list_left = list_count;
		solution = puzzle;
		% Fill in values to optimize the rows
		for r=id
        %for r = 1:9
			% Fill in values for all empty spaces in this row
			for c = 1:9
				if free(r,c)
					list_index = ceil(rand*list_left);
					solution(r,c) = list(list_index);
					list(list_index)=[];
					list_left = list_left-1;
				end
			end
			list(end+1:list_count) = 1e10;
			if list_left
				%  Get row as close as possible to
				%  target value
				row_total = sum(solution(r,:)) - target;
				est_error = abs(row_total);
				tq = r + 9*(find(free(r,:))-1);
				indv = tq(ceil(rand(NUMTRIES1,1)*numel(tq)));
				for tries = 1:NUMTRIES1
					ind = indv(tries);
					list_index = ceil(rand*list_left);
					list_value = list(list_index);
					delta = list_value - solution(ind);
					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(ind);
						solution(ind) = list_value;
					end
				end
			end
		end
	
		target = sum(sum(solution)) *0.1111111111111111;
		
		% 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:NUMTRIES2         
                  row        = scale_row + ceil(rand*3);
                  col_inside = scale_col + ceil(rand*3);
                  if free(row,col_inside)
                    col_outside = cols_all_outside(ceil(rand*6));
                    if free(row,col_outside)
                      val_inside  = solution(row, col_inside);
                      val_outside = solution(row, col_outside);
                      new_block   = block - val_inside + val_outside;
                      if abs(new_block - target) < abs(block - target)
                        solution(row,col_outside) = val_inside;
                        solution(row,col_inside)  = val_outside;
                        block                     = new_block;
                      end    
                    end
                  end
                end
			end
		end
	
		%Solve the columns without changing rows or blocks
		col_total = sum(solution) - target;
		for tries = 1:NUMTRIES3
			el = q(ceil(rand*missing));
			col = colmap(el);
			row = el - 9*(col-1);
			col_swap = ceil(rand*3) + (ceil(col/3)-1)*3;
			if free(row,col_swap)
				value_swap = solution(row,col_swap);
				error = abs(col_total(col));
				value = solution(row,col);
				col_swap_total = col_total(col_swap);
				col_total_new = col_total(col) + value_swap - value;
				col_swap_total_new = col_swap_total + value - value_swap;
				error_total_new = abs(col_total_new) + abs(col_swap_total_new);
				if (error_total_new < error + abs(col_swap_total))
					solution(el) = value_swap;
					solution(row, col_swap) = value;
					col_total(col_swap) = col_swap_total_new;
					col_total(col) = col_total_new;
				end
			end
		end
	
		sums  = sum(solution(iX));
		score = sum(abs(sum(sums)*0.03703703703703703703-sums));
		if score < bestscore
			bestinit = solution;
			bestscore = score;
			bestlist = list;
		end
	
		solution = bestinit;
		list = bestlist;
		coltotals = sum(solution);
		rowtotals = sum(solution,2)';
		blocktotals = sum(solution(h));
		target = sum(coltotals)*0.11111111111111111111111;
		
		if list_left ~= 0
			rep = 0;
			for repl = 1:5000 %  blimey! loop unroll! (drumroll?)
				target3=target*3; %constant for loop 0-3
				% ----- loop 0,  do the first thing (loops 0-3 are the same)
				rep = rep + 1;
				index1 = index1v(rep);     index2 = index2v(rep);
				index1r = rowmap(index1);  index2r = rowmap(index2);
				index1c = colmap(index1);  index2c = colmap(index2);
				value1 = solution(index1); value2 = solution(index2);
				block1i = blockmap(index1);block2i = blockmap(index2);
				valdiff = value1-value2;
                nvd=iN(index1,index2)*valdiff;
				subtotal1_old = rowtotals(index1r) + coltotals(index1c) + blocktotals(block1i) - target3;
				subtotal2_old = rowtotals(index2r) + coltotals(index2c) + blocktotals(block2i) - target3;
				subscoret_old = abs(subtotal1_old) + abs(subtotal2_old);
				subscoret_new = abs(subtotal1_old-nvd) + abs(subtotal2_old+nvd); 
				if (subscoret_new - subscoret_old) < (rand*0.1666666667)
					solution(index1) = value2;
					solution(index2) = value1;
					% dont bother to compare if the rows/cols are the same..
					rowtotals(index1r) = rowtotals(index1r) - valdiff;
					rowtotals(index2r) = rowtotals(index2r) + valdiff;
					coltotals(index1c) = coltotals(index1c) - valdiff;
					coltotals(index2c) = coltotals(index2c) + valdiff;
					blocktotals(block1i) = blocktotals(block1i) - valdiff;
					blocktotals(block2i) = blocktotals(block2i) + valdiff;
				end
				% ----- loop 1,  do the first thing
				rep = rep + 1;
				index1 = index1v(rep);     index2 = index2v(rep);
				index1r = rowmap(index1);  index2r = rowmap(index2);
				index1c = colmap(index1);  index2c = colmap(index2);
				value1 = solution(index1); value2 = solution(index2);
				block1i = blockmap(index1);block2i = blockmap(index2);
				valdiff = value1-value2;
                nvd=iN(index1,index2)*valdiff;
				subtotal1_old = rowtotals(index1r) + coltotals(index1c) + blocktotals(block1i) - target3;
				subtotal2_old = rowtotals(index2r) + coltotals(index2c) + blocktotals(block2i) - target3;
				subscoret_old = abs(subtotal1_old) + abs(subtotal2_old);
				subscoret_new = abs(subtotal1_old-nvd) + abs(subtotal2_old+nvd); 
				if (subscoret_new - subscoret_old) < (rand*0.1666666667)
					solution(index1) = value2;
					solution(index2) = value1;
					% dont bother to compare if the rows/cols are the same..
					rowtotals(index1r) = rowtotals(index1r) - valdiff;
					rowtotals(index2r) = rowtotals(index2r) + valdiff;
					coltotals(index1c) = coltotals(index1c) - valdiff;
					coltotals(index2c) = coltotals(index2c) + valdiff;
					blocktotals(block1i) = blocktotals(block1i) - valdiff;
					blocktotals(block2i) = blocktotals(block2i) + valdiff;
				end
				% ----- loop 2,  do the first thing
				rep = rep + 1;
				index1 = index1v(rep);     index2 = index2v(rep);
				index1r = rowmap(index1);  index2r = rowmap(index2);
				index1c = colmap(index1);  index2c = colmap(index2);
				value1 = solution(index1); value2 = solution(index2);
				block1i = blockmap(index1);block2i = blockmap(index2);
				valdiff = value1-value2;
                nvd=iN(index1,index2)*valdiff;
				subtotal1_old = rowtotals(index1r) + coltotals(index1c) + blocktotals(block1i) - target3;
				subtotal2_old = rowtotals(index2r) + coltotals(index2c) + blocktotals(block2i) - target3;
				subscoret_old = abs(subtotal1_old) + abs(subtotal2_old);
				subscoret_new = abs(subtotal1_old-nvd) + abs(subtotal2_old+nvd); 
				if (subscoret_new - subscoret_old) < (rand*0.166666667)
					solution(index1) = value2;
					solution(index2) = value1;
					% dont bother to compare if the rows/cols are the same..
					rowtotals(index1r) = rowtotals(index1r) - valdiff;
					rowtotals(index2r) = rowtotals(index2r) + valdiff;
					coltotals(index1c) = coltotals(index1c) - valdiff;
					coltotals(index2c) = coltotals(index2c) + valdiff;
					blocktotals(block1i) = blocktotals(block1i) - valdiff;
					blocktotals(block2i) = blocktotals(block2i) + valdiff;
				end
				% ----- loop 3,  do the first thing
				rep = rep + 1;
				index1 = index1v(rep);     index2 = index2v(rep);
				index1r = rowmap(index1);  index2r = rowmap(index2);
				index1c = colmap(index1);  index2c = colmap(index2);
				value1 = solution(index1); value2 = solution(index2);
				block1i = blockmap(index1);block2i = blockmap(index2);
				valdiff = value1-value2;
                nvd=iN(index1,index2)*valdiff;
				subtotal1_old = rowtotals(index1r) + coltotals(index1c) + blocktotals(block1i) - target3;
				subtotal2_old = rowtotals(index2r) + coltotals(index2c) + blocktotals(block2i) - target3;
				subscoret_old = abs(subtotal1_old) + abs(subtotal2_old);
				subscoret_new = abs(subtotal1_old-nvd) + abs(subtotal2_old+nvd); 
				if (subscoret_new - subscoret_old) < (rand*0.1666666667)
					solution(index1) = value2;
					solution(index2) = value1;
					% dont bother to compare if the rows/cols are the same..
					rowtotals(index1r) = rowtotals(index1r) - valdiff;
					rowtotals(index2r) = rowtotals(index2r) + valdiff;
					coltotals(index1c) = coltotals(index1c) - valdiff;
					coltotals(index2c) = coltotals(index2c) + valdiff;
					blocktotals(block1i) = blocktotals(block1i) - valdiff;
					blocktotals(block2i) = blocktotals(block2i) + valdiff;
				end
				%------ loop 4, do the other thing
				rep = rep+1;
				index1 = index1v(rep);
				index1r = rowmap(index1);
				index1c = colmap(index1);
				value1 = solution(index1);
				block1i = blockmap(index1);
				list_index = ceil(rand*list_left);
				replace = list(list_index);
				subtotal1_old = rowtotals(index1r) + coltotals(index1c) + blocktotals(block1i);
                newtarg = target + (replace-value1) *0.1111111111111;
				score_diff = abs(subtotal1_old+3*(replace-value1-newtarg)) - abs(subtotal1_old - 3*target);
				if score_diff < 0.93*rand
					solution(index1) = replace;
					list(list_index) = value1;
                    delta=replace-value1;
					rowtotals(index1r) = rowtotals(index1r) + delta;
					coltotals(index1c) = coltotals(index1c) + delta;
					blocktotals(block1i) = blocktotals(block1i) + delta;
					target = newtarg;
				end
				% ---- end loop
			end
		
		else % (list_left == 0)
	
			% time for fresh random numbers...
			index1v = ceil(rand(NUMREPS,1)*lq);
			index1v = q(index1v);
			sok=NUMREPS-350;
            target3=target*3;   %constant target
			for rep = 1:sok
				% --- this is same as the "first thing" above
				index1 = index1v(rep);     index2 = index2v(rep);
				index1r = rowmap(index1);  index2r = rowmap(index2);
				index1c = colmap(index1);  index2c = colmap(index2);
				value1 = solution(index1); value2 = solution(index2);
				block1i = blockmap(index1);block2i = blockmap(index2);
				
				valdiff = value1-value2;
                nvd=iN(index1,index2)*valdiff;

				subtotal1_old = rowtotals(index1r) + coltotals(index1c) + blocktotals(block1i) - target3;
				subtotal2_old = rowtotals(index2r) + coltotals(index2c) + blocktotals(block2i) - target3;
				subscoret_old = abs(subtotal1_old) + abs(subtotal2_old);
                                subscoret_new = abs(subtotal1_old-nvd) + abs(subtotal2_old+nvd); 
				
				if (subscoret_new - subscoret_old) < (rand*0.1666666667)
					solution(index1) = value2;
					solution(index2) = value1;
					% dont bother to compare if the rows/cols are the same..
					rowtotals(index1r) = rowtotals(index1r) - valdiff;
					rowtotals(index2r) = rowtotals(index2r) + valdiff;
					coltotals(index1c) = coltotals(index1c) - valdiff;
					coltotals(index2c) = coltotals(index2c) + valdiff;
					blocktotals(block1i) = blocktotals(block1i) - valdiff;
					blocktotals(block2i) = blocktotals(block2i) + valdiff;
				end
			
			end
		end
		% --- end the inner loop
		
		sums  = sum(solution(iX));
		score = sum(abs(sum(sums)*0.037037037-sums));
		if score < bestscore2
			bestsol = solution;
			bestscore2 = score;
		end
		if bestscore2 < 5
			break
		end
	end
	if ( reruns==0 && bestscore2>9 )
		reruns=reruns+1;
	elseif ( reruns==1 && bestscore2>25 )
		reruns=reruns+1;
	else
		reruns=1e8;
	end
end
solution = bestsol;
% --- prepare for final improvers
n=ceil(bestscore2);
X = solution(iX);
sX = sum(X);
mX = sum(sX)*0.037037037;
XX=zeros(81,3);
for i=q
	XX(i,:)=find(sum(iX==i));
end

for i=1:n
	bVerb=0;
	for iEl=q
		I=XX(iEl,:);
		s1=sum(sX(I)-mX);
		if (s1>0&&sum(sX(I)>mX)<2)||(s1<0&&sum(sX(I)<mX)<2)
			continue
		end
		x=solution(iEl);
		dx=solution(q)-x;
		if s1>0
			j=find(dx<0.8&dx+s1*2>0&dx~=0);
		else
			j=find(dx>-0.8&dx+s1*2<0&dx~=0);
		end
		if ~isempty(j)
			S0=sX-mX;
			s=sum(abs(S0));
			m=0;
            kozz=numel(j);
			for k=1:kozz
				S=S0;
				S(I)=S(I)+dx(j(k));
				J=XX(q(j(k)),:);
				S(J)=S(J)-dx(j(k));
				T=sum(abs(S));
				if T<s
					m=k;
					s=T;
				end
			end
			if m
				j=q(j(m));
				solution(iEl)=solution(j);
				solution(j)=x;
				X=solution(iX);
				sX=sum(X);
				bVerb=1;
				
			end
		end
	end
	if ~bVerb
		break
	end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [out,vprev]=improver3(list,solution,idx)
%Initialize
y=ceil(idx*0.111);
x=idx-(y-1)*9;
a=solution(idx);
a=[a ; list(~ismembc(list,sort(a)))];
N1=numel(idx);

% Initialise the square indices
isquare = [ 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];
square=[1     1     1     4     4     4     7     7     7
     1     1     1     4     4     4     7     7     7
     1     1     1     4     4     4     7     7     7
     2     2     2     5     5     5     8     8     8
     2     2     2     5     5     5     8     8     8
     2     2     2     5     5     5     8     8     8
     3     3     3     6     6     6     9     9     9
     3     3     3     6     6     6     9     9     9
     3     3     3     6     6     6     9     9     9];
% Initialise the solution
out=solution;
N=numel(a)-N1;

% Calculate bounds on the block values
rowsum=sum(out,2);
optsum=sum(rowsum)*0.11111111111;
colsum=sum(out,1)';
sqsum=sum(out(isquare),2);
S=[rowsum(x) colsum(y) sqsum(square(idx))]-optsum;
vprev=Inf;
ii=1; cnt=1;
while 1                         
    yy=ii+1;
	tmp=S(zeros(numel(a)-ii,1)+ii,:);
	tmp=tmp+a(yy:end,[1 1 1])-a(ii);
	tmp=sum(abs(tmp),2)-sum(abs(S(ii,:)));
	tmp2=S(yy:end,:)-a(yy:numel(idx),[1 1 1])+a(ii);
        tmp2=[sum(abs(tmp2),2)-sum(abs(S(yy:end,:)),2) ; zeros(N,1)];
        tmp=tmp+tmp2;
	[tmp,idx3]=min(tmp);
	if (tmp<0)                      % Replace one list value by another
        zz = idx3+ii;
		tmp=a(zz); a(zz)=a(ii); a(ii)=tmp;
		out(x(ii),y(ii))=a(ii);
		if (zz<=size(S,1)) % Swaps the two currently used list values
			out(x(zz),y(zz))=a(zz);
		else                    % Re-calculate the optimal sum
			optsum=optsum+(a(ii)-a(zz)) *0.111111111111111;
		end                             % Re-calculate the various sums
		rowsum=sum(out,2);
		colsum=sum(out,1)';
		sqsum=sum(out(isquare),2);
		S=[rowsum(x) colsum(y) sqsum(square(idx))]-optsum;
	end
	if (ii==1)
		sums  = [rowsum ; colsum ; sqsum];
		v = sum(abs(sum(sums)/numel(sums)-sums));
		if (v>=vprev)
			break
		end
		vprev=v;
	end
	ii=yy;
	if (ii==size(S,1))
		ii=1;
		cnt=cnt+1;
		if (cnt==4)
			break
		end
	end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% All of the previous algorithms have focussed on pairwise switching
% of weights. The main loop is a fast random method for choosing the
% blocks to be switched. What follows that (formerly improver2) is a 
% slower method comparing the scores before and after each pair of blocks 
% already in the matrix have been swapped. Then improver3 is a faster 
% method of doing the same thing, but only approximates the change in 
% score, and also allows swaps with unassigned elements in the list. 
% This improver looks at swapping three elements at a time (although 
% not exhaustively), and can trivially be altered for more than three 
% elements (increasing to more than 3 would probably minimally affect 
% the score though).

function [solution,flag]=improver4(solution,list,idx)

global iX

%Initialize

a=solution(idx); N=numel(a);
a=[a ; list(~ismembc(list,sort(a)))];

sums = sum(solution(iX));
bsc  = sum(abs(sum(sums) *0.0370370370370370-sums)); bsc2=bsc;
ba   = a;

[b,idx2]=sort(a);
zok=numel(a)-2;
for ii=1:zok
  tmp=a(idx2(ii:ii+2));

  a=ba;
  a(idx2(ii:ii+2))=[tmp(2:3) ; tmp(1)];

  solution(idx)=a(1:N);
  
  sums  = sum(solution(iX));
  score = sum(abs(sum(sums) *0.037037037037-sums));
  if (score<bsc) bsc=score; ba=a; continue; end;

  tmp=[tmp(2:3) ; tmp(1)];
  a(idx2(ii:ii+2))=[tmp(2:3) ; tmp(1)];
  solution(idx)=a(1:N);

  sums  = sum(solution(iX));
  score = sum(abs(sum(sums) *0.037037037-sums));
  if (score<bsc) bsc=score; ba=a; continue; end;

  a(idx2(ii:ii+2))=tmp([3;1;2]);

end;

flag=(bsc<bsc2);
solution(idx)=ba(1:N);