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