examples/numbrix.mod
changeset 1 c445c931472f
equal deleted inserted replaced
-1:000000000000 0:7c653c95b1f0
       
     1 /* Numbrix, Number Placement Puzzle */
       
     2 
       
     3 /* Written in GNU MathProg by Robert Wood <rwood@targus.com>  */
       
     4 
       
     5 /* Numbrix is a logic-based number-placement puzzle.[1]
       
     6  * The objective is to fill the grid so that each cell contains
       
     7  * digits in sequential order taking a horizontal or vertical
       
     8  * path; diagonal paths are not allowed. The puzzle setter
       
     9  * provides a grid often with the outer most cells completed.
       
    10  *
       
    11  * Completed Numbrix puzzles are usually a square of numbers
       
    12  * in order from 1 to 64 (8x8 grid) or from 1 to 81 (9x9 grid),
       
    13  * following a continuous path in sequence.
       
    14  *
       
    15  * The modern puzzle was invented by Marilyn vos Savant in 2008
       
    16  * and published by Parade Magazine under the name "Numbrix",
       
    17  * near her weekly Ask Marilyn article.
       
    18  *
       
    19  *    http://en.wikipedia.org/wiki/Numbrix  */
       
    20 
       
    21 set I := {1..9};
       
    22 set J := {1..9};
       
    23 set VALS := {1..81};
       
    24 
       
    25 param givens{I, J}, integer, >= 0, <= 81, default 0;
       
    26 /* the "givens" */
       
    27 
       
    28 param neighbors{i in I,j in J, i2 in I, j2 in J} , binary :=
       
    29 (if abs(i - i2) + abs(j -j2) == 1 then
       
    30      1
       
    31  else
       
    32      0
       
    33 );
       
    34 /*  defines which spots are the boards are neighbors */
       
    35 
       
    36 var x{i in I, j in J, k in VALS}, binary;
       
    37 /* x[i,j,k] = 1 means cell [i,j] is assigned number k */
       
    38 
       
    39 s.t. fa{i in I, j in J, k in VALS: givens[i,j] != 0}:
       
    40      x[i,j,k] = (if givens[i,j] = k then 1 else 0);
       
    41 /* assign pre-defined numbers using the "givens" */
       
    42 
       
    43 s.t. fb{i in I, j in J}: sum{k in VALS} x[i,j,k] = 1;
       
    44 /* each cell must be assigned exactly one number */
       
    45 
       
    46 s.t. singleNum {k in VALS}:  sum{i in I, j in J} x[i,j,k] = 1;
       
    47 /*  a value can only occur once */
       
    48 
       
    49 s.t. neighborContraint {i in I, j in J, k in 1..80}:
       
    50         x[i,j,k] <= sum{i2 in I, j2 in J} x[i2,j2,k+1] * neighbors[i,j,i2,j2];
       
    51 /* each cell must have a neighbor with the next higher value */
       
    52 
       
    53 
       
    54 /* there is no need for an objective function here */
       
    55 
       
    56 
       
    57 solve;
       
    58 
       
    59 for {i in I}
       
    60 {  for {0..0: i = 1 or i = 4 or i = 7}
       
    61       printf " +----------+----------+----------+\n";
       
    62    for {j in J}
       
    63    {  for {0..0: j = 1 or j = 4 or j = 7} printf(" |");
       
    64       printf " %2d", sum{k in VALS} x[i,j,k] * k;
       
    65       for {0..0: j = 9} printf(" |\n");
       
    66    }
       
    67    for {0..0: i = 9}
       
    68       printf " +----------+----------+----------+\n";
       
    69 }
       
    70 
       
    71 data;
       
    72 
       
    73 param givens : 1 2 3 4 5 6 7 8 9 :=
       
    74            1   . . . . . . . . .
       
    75            2   . 11 12 15 18 21 62 61 .
       
    76            3   .  6 . . . . . 60 .
       
    77            4   . 33 . . . . . 57 .
       
    78            5   . 32 . . . . . 56 .
       
    79            6   . 37 . . . . . 73 .
       
    80            7   . 38 . . . . . 72 .
       
    81            8   . 43 44 47 48 51 76 77 .
       
    82            9   . . . . . . . . . ;
       
    83 
       
    84 end;