alpar@1: /* A solver for the Japanese number-puzzle Shikaku alpar@1: * http://en.wikipedia.org/wiki/Shikaku alpar@1: * alpar@1: * Sebastian Nowozin , 27th January 2009 alpar@1: */ alpar@1: alpar@1: param ndim := 10; alpar@1: set rows := 1..ndim; alpar@1: set rows1 := 1..(ndim+1); alpar@1: set cols := 1..ndim; alpar@1: set cols1 := 1..(ndim+1); alpar@1: param givens{rows, cols}, integer, >= 0, default 0; alpar@1: alpar@1: /* Set of vertices as (row,col) coordinates */ alpar@1: set V := { (i,j) in { rows, cols }: givens[i,j] != 0 }; alpar@1: alpar@1: /* Set of all feasible boxes of the right size: only this boxes are possible. alpar@1: * The box contains (i,j) and ranges from (k,l) to (m,n) alpar@1: */ alpar@1: set B := { (i,j,k,l,m,n) in { V, rows, cols, rows1, cols1 }: alpar@1: i >= k and i < m and j >= l and j < n and /* Contains (i,j) */ alpar@1: ((m-k)*(n-l)) = givens[i,j] and /* Right size */ alpar@1: card({ (s,t) in V: s >= k and s < m and t >= l and t < n }) = 1 alpar@1: /* Contains only (i,j), no other number */ alpar@1: }; alpar@1: alpar@1: var x{B}, binary; alpar@1: alpar@1: /* Cover each square exactly once */ alpar@1: s.t. cover_once{ (s,t) in { rows, cols } }: alpar@1: sum{(i,j,k,l,m,n) in B: s >= k and s < m and t >= l and t < n} alpar@1: x[i,j,k,l,m,n] = 1; alpar@1: alpar@1: minimize cost: 0; alpar@1: alpar@1: solve; alpar@1: alpar@1: /* Output solution graphically */ alpar@1: printf "\nSolution:\n"; alpar@1: for { row in rows1 } { alpar@1: for { col in cols1 } { alpar@1: printf{0..0: card({(i,j,k,l,m,n) in B: alpar@1: col >= l and col <= n and (row = k or row = m) and alpar@1: x[i,j,k,l,m,n] = 1}) > 0 and alpar@1: card({(i,j,k,l,m,n) in B: alpar@1: row >= k and row <= m and (col = l or col = n) and alpar@1: x[i,j,k,l,m,n] = 1}) > 0} "+"; alpar@1: printf{0..0: card({(i,j,k,l,m,n) in B: alpar@1: col >= l and col <= n and (row = k or row = m) and alpar@1: x[i,j,k,l,m,n] = 1}) = 0 and alpar@1: card({(i,j,k,l,m,n) in B: alpar@1: row >= k and row <= m and (col = l or col = n) and alpar@1: x[i,j,k,l,m,n] = 1}) > 0} "|"; alpar@1: printf{0..0: card({(i,j,k,l,m,n) in B: alpar@1: row >= k and row <= m and (col = l or col = n) and alpar@1: x[i,j,k,l,m,n] = 1}) = 0 and alpar@1: card({(i,j,k,l,m,n) in B: alpar@1: col >= l and col <= n and (row = k or row = m) and alpar@1: x[i,j,k,l,m,n] = 1}) > 0} "-"; alpar@1: printf{0..0: card({(i,j,k,l,m,n) in B: alpar@1: row >= k and row <= m and (col = l or col = n) and alpar@1: x[i,j,k,l,m,n] = 1}) = 0 and alpar@1: card({(i,j,k,l,m,n) in B: alpar@1: col >= l and col <= n and (row = k or row = m) and alpar@1: x[i,j,k,l,m,n] = 1}) = 0} " "; alpar@1: alpar@1: printf{0..0: card({(i,j,k,l,m,n) in B: alpar@1: col >= l and col < n and (row = k or row = m) and alpar@1: x[i,j,k,l,m,n] = 1}) > 0} "---"; alpar@1: printf{0..0: card({(i,j,k,l,m,n) in B: alpar@1: col >= l and col < n and (row = k or row = m) and alpar@1: x[i,j,k,l,m,n] = 1}) = 0} " "; alpar@1: } alpar@1: printf "\n"; alpar@1: alpar@1: for { (col,p) in { cols, 1 }: card({ s in rows: s = row }) = 1 } { alpar@1: printf{0..0: card({(i,j,k,l,m,n) in B: alpar@1: row >= k and row < m and (col = l or col = n) and alpar@1: x[i,j,k,l,m,n] = 1}) > 0} "|"; alpar@1: printf{0..0: card({(i,j,k,l,m,n) in B: alpar@1: row >= k and row < m and (col = l or col = n) and alpar@1: x[i,j,k,l,m,n] = 1}) = 0} " "; alpar@1: printf{0..0: card({ (i,j) in V: i = row and j = col}) > 0} " %2d", givens[row,col]; alpar@1: printf{0..0: card({ (i,j) in V: i = row and j = col}) = 0} " ."; alpar@1: } alpar@1: printf{0..0: card({ r in rows: r = row }) = 1} "|\n"; alpar@1: } alpar@1: alpar@1: data; alpar@1: alpar@1: /* This Shikaku is from alpar@1: * http://www.emn.fr/x-info/sdemasse/gccat/KShikaku.html#uid5449 alpar@1: */ alpar@1: param givens : 1 2 3 4 5 6 7 8 9 10 := alpar@1: 1 9 . . . 12 . . 5 . . alpar@1: 2 . . . . . . . . . . alpar@1: 3 . . . . . . . . . 6 alpar@1: 4 8 . 6 . 8 . . . . . alpar@1: 5 . . . . . . . . . . alpar@1: 6 . . . . . . . . . . alpar@1: 7 . . . . . 6 . 8 . 12 alpar@1: 8 4 . . . . . . . . . alpar@1: 9 . . . . . . . . . . alpar@1: 10 . . 3 . . 9 . . . 4 alpar@1: ; alpar@1: alpar@1: end;