alpar@1: /* Numbrix, Number Placement Puzzle */ alpar@1: alpar@1: /* Written in GNU MathProg by Robert Wood */ alpar@1: alpar@1: /* Numbrix is a logic-based number-placement puzzle.[1] alpar@1: * The objective is to fill the grid so that each cell contains alpar@1: * digits in sequential order taking a horizontal or vertical alpar@1: * path; diagonal paths are not allowed. The puzzle setter alpar@1: * provides a grid often with the outer most cells completed. alpar@1: * alpar@1: * Completed Numbrix puzzles are usually a square of numbers alpar@1: * in order from 1 to 64 (8x8 grid) or from 1 to 81 (9x9 grid), alpar@1: * following a continuous path in sequence. alpar@1: * alpar@1: * The modern puzzle was invented by Marilyn vos Savant in 2008 alpar@1: * and published by Parade Magazine under the name "Numbrix", alpar@1: * near her weekly Ask Marilyn article. alpar@1: * alpar@1: * http://en.wikipedia.org/wiki/Numbrix */ alpar@1: alpar@1: set I := {1..9}; alpar@1: set J := {1..9}; alpar@1: set VALS := {1..81}; alpar@1: alpar@1: param givens{I, J}, integer, >= 0, <= 81, default 0; alpar@1: /* the "givens" */ alpar@1: alpar@1: param neighbors{i in I,j in J, i2 in I, j2 in J} , binary := alpar@1: (if abs(i - i2) + abs(j -j2) == 1 then alpar@1: 1 alpar@1: else alpar@1: 0 alpar@1: ); alpar@1: /* defines which spots are the boards are neighbors */ alpar@1: alpar@1: var x{i in I, j in J, k in VALS}, binary; alpar@1: /* x[i,j,k] = 1 means cell [i,j] is assigned number k */ alpar@1: alpar@1: s.t. fa{i in I, j in J, k in VALS: givens[i,j] != 0}: alpar@1: x[i,j,k] = (if givens[i,j] = k then 1 else 0); alpar@1: /* assign pre-defined numbers using the "givens" */ alpar@1: alpar@1: s.t. fb{i in I, j in J}: sum{k in VALS} x[i,j,k] = 1; alpar@1: /* each cell must be assigned exactly one number */ alpar@1: alpar@1: s.t. singleNum {k in VALS}: sum{i in I, j in J} x[i,j,k] = 1; alpar@1: /* a value can only occur once */ alpar@1: alpar@1: s.t. neighborContraint {i in I, j in J, k in 1..80}: alpar@1: x[i,j,k] <= sum{i2 in I, j2 in J} x[i2,j2,k+1] * neighbors[i,j,i2,j2]; alpar@1: /* each cell must have a neighbor with the next higher value */ alpar@1: alpar@1: alpar@1: /* there is no need for an objective function here */ alpar@1: alpar@1: alpar@1: solve; alpar@1: alpar@1: for {i in I} alpar@1: { for {0..0: i = 1 or i = 4 or i = 7} alpar@1: printf " +----------+----------+----------+\n"; alpar@1: for {j in J} alpar@1: { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); alpar@1: printf " %2d", sum{k in VALS} x[i,j,k] * k; alpar@1: for {0..0: j = 9} printf(" |\n"); alpar@1: } alpar@1: for {0..0: i = 9} alpar@1: printf " +----------+----------+----------+\n"; alpar@1: } alpar@1: alpar@1: data; alpar@1: alpar@1: param givens : 1 2 3 4 5 6 7 8 9 := alpar@1: 1 . . . . . . . . . alpar@1: 2 . 11 12 15 18 21 62 61 . alpar@1: 3 . 6 . . . . . 60 . alpar@1: 4 . 33 . . . . . 57 . alpar@1: 5 . 32 . . . . . 56 . alpar@1: 6 . 37 . . . . . 73 . alpar@1: 7 . 38 . . . . . 72 . alpar@1: 8 . 43 44 47 48 51 76 77 . alpar@1: 9 . . . . . . . . . ; alpar@1: alpar@1: end;